我正在使用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))
有帮助吗?

解决方案

我看到几个问题。我将描述它们,并提供一个代码片段,应该可以正常工作,因为我相信你希望这个样本能够工作。

你的第一个问题是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代码的nits是数字类型真的应拼写为 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))

我应该补充一点,我实际上并没有编译并运行上面的内容,因此可能会有一两个错误或者两个作为练习; - )

其他提示

如果你要做大量的C ++到lua绑定,你可能想看看 luabind

如果您要编译为C ++并希望匹配“C”接口,则应将外部可见的函数声明为 extern" C" 以避免名称损坏。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top