views:

705

answers:

3

I'm using Visual Studio 2005.

------------------------[ luapassing.cpp ]--------------------

#include "lua.h"
static int myCfunc (Lua_State *L){
   double trouble = lua_tonumber(L,1);
   lua_pushnumber(L,16.0 -trouble);
   return 1;
}
int luaopen_luapassing (Lua_State *L){
   static const lua_reg Map [] = {{"dothis",myCfunc},{NULL,NULL}};
   luaL_register(L,"cstuff",Map);
   return;
}

-------------------------[ csample.lua ]-------------------------

package.cpath = "./CLua2.dll"
require "luapassing"

print("hola")
print(seth.doThis(120))
+1  A: 

If you are compiling as C++ and want to match a 'C' interface, you should declare the externally visible functions as extern "C" to avoid name mangling.

Steve Gilham
I don't think this is necessary. When linking the Lua runtime to a C++ project, only the Lua stuff needs to be extern "C". At least that's how I set things up.
Andy J Buchanan
As I explain in my answer, it is critical that the luaopen_modulename() function be extern "C" unless the Lua core itself was compiled as C++. Even then, due to quirks with DLLs, you may be better off leaving it extern "C" to avoid issues if more than one compiler is used in a project.
RBerteig
+2  A: 

If you're going to be doing a lot of C++ to lua binding, you might want to take a look at luabind.

mattnewport
+4  A: 

I see several issues. I'll describe them, and provide a code fragment that should work as I believe you intended this sample to work.

Your first problem is that the C++ compiler mangled the name of the only function exported from your DLL whose name matters to Lua: luaopen_luapassing(). The stock binary distribution for Windows was compiled as a C program, and assumes a C style name for the DLL module entry point.

Also, you have the protocol for the luaopen_x function slightly wrong. The function returns an integer which tells Lua how many items on the top of Lua's stack are return values for use by Lua. The protocol assumed by require would prefer that you leave the new module's table object on the top of the stack and return it to Lua. To do this, the luaopen_x function would ordinarily use luaL_register() as you did, then return 1.

There is also the issue of naming. Modules written in pure Lua have the opportunity to be less aware of their names. But modules written in C have to export a function from the DLL that includes the module name in its name. They also have to provide that module name to luaL_register() so that the right table is created and updated in the global environment. Finally, the client Lua script will see the loaded module in a global table named like the name passed to require, which is also returned from require so that it may be cached in a local in that script.

A couple of other nits with the C code are that the numeric type really should be spelled lua_Number for portability, and that it would be conventional to use luaL_checknumber() rather than lua_tonumber() to enforce the required argument to the function. Personally, I would name the C implementation of a public function with a name related to its name that will be known publicly by Lua, but that is just a matter of taste.

This version of the C side should fix these issues:

#include "lua.h"
static int my_dothis (Lua_State *L){
   lua_Number trouble = luaL_checknumber(L,1);
   lua_pushnumber(L,16.0 -trouble);
   return 1;
}
extern "C" int luaopen_luapassing (Lua_State *L){
    static const lua_reg Map [] = {
        {"dothis", my_dothis},
        {NULL,NULL}
    };
    luaL_register(L,"luapassing",Map);
    return 1;
}

The sample script then needs to refer to the loaded module by its proper name, and to the functions defined by that module by their proper names. Lua is case sensitive, so if the module creates a function named dothis(), then the script must use that same name, and cannot find it named doThis(), for example.

require "luapassing"

print("hola")
print(luapassing.dothis(120))

I should add that I haven't actually compiled and run the above, so there might be a typo or two left as an exercise ;-)

RBerteig