【问题标题】:How do I call C++ functions from a Lua script?如何从 Lua 脚本调用 C++ 函数?
【发布时间】:2010-11-15 15:15:23
【问题描述】:

我使用的是 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++ visual-c++ lua


    【解决方案1】:

    我看到了几个问题。我将对它们进行描述,并提供一个代码片段,我相信它应该可以按照您希望此示例正常工作的方式工作。

    您的第一个问题是 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() 的函数。

    需要“luapassing” 打印(“你好”) 打印(luapassing.dothis(120))

    我应该补充一点,我实际上并没有编译和运行上面的代码,所以可能会有一两个错字作为练习;-)

    【讨论】:

      【解决方案2】:

      如果你打算做很多 C++ 到 lua 绑定,你可能想看看luabind

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 正如我在回答中解释的那样,luaopen_modulename() 函数必须是 extern "C",除非 Lua 核心本身被编译为 C++。即使这样,由于 DLL 的怪癖,如果在一个项目中使用多个编译器,您最好将其保留为 extern "C" 以避免出现问题。
        猜你喜欢
        • 2018-04-23
        • 1970-01-01
        • 2018-08-31
        • 1970-01-01
        • 1970-01-01
        • 2017-01-07
        • 2019-07-30
        • 2015-07-14
        • 2013-08-24
        相关资源
        最近更新 更多