我正在使用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))
答案 0 :(得分:5)
我看到几个问题。我将描述它们,并提供一个代码片段,应该可以正常工作,因为我相信你希望这个样本能够工作。
你的第一个问题是C ++编译器破坏了从你的DLL导出的唯一函数的名称,其名称对Lua来说很重要:luaopen_luapassing()
。 Windows的库存二进制分发版编译为C程序,并假定DLL模块入口点的C样式名称。
此外,您对luaopen_x
功能的协议略有错误。该函数返回一个整数,告诉Lua Lua堆栈顶部有多少项是Lua使用的返回值。 require
假定的协议更喜欢将新模块的表对象保留在堆栈顶部并将其返回给Lua。为此,luaopen_x
函数通常会使用luaL_register()
,然后返回1.
还有命名问题。用纯Lua编写的模块有机会不太了解它们的名字。但是用C编写的模块必须从DLL中导出一个函数,该函数名称中包含模块名称。他们还必须将该模块名称提供给luaL_register()
,以便在全局环境中创建和更新正确的表。最后,客户端Lua脚本将在名为传递给require
的名称的全局表中看到已加载的模块,该表也从require
返回,以便它可以缓存在该脚本的本地中。
使用C代码的其他几个问题是数字类型确实应该拼写为lua_Number
以便于移植,并且使用luaL_checknumber()
而不是lua_tonumber()
是常规的强制执行函数所需的参数。就个人而言,我会将一个名为与其名称相关的公共函数的C实现命名为Lua公开,但这只是一个品味问题。
此版本的C端应解决这些问题:
#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;
}
然后,示例脚本需要通过其正确的名称引用加载的模块,并通过其正确的名称引用该模块定义的函数。 Lua区分大小写,因此如果模块创建名为dothis()
的函数,则脚本必须使用相同的名称,并且例如找不到名为doThis()
的名称。
require "luapassing" print("hola") print(luapassing.dothis(120))
我应该补充一点,我实际上并没有编译并运行上面的内容,因此可能会有一两个错误或者两个作为练习; - )
答案 1 :(得分:3)
如果您要进行大量的C ++到lua绑定,您可能需要查看luabind。
答案 2 :(得分:2)
如果您要编译为C ++并希望匹配“C”接口,则应将外部可见函数声明为extern "C"
以避免名称损坏。