如何使用Lua C API绑定C ++成员方法和成员变量?

时间:2014-05-22 11:10:07

标签: c++ lua

到目前为止我所做的所有谷歌搜索都发现了非常接近的事情,但并不是因为我试图做的事情而完全削减它。

让我以最基本的方式对此进行描述:

  • 想象一下你有一个C ++类

    class A
    {
    public:
        int Method();
        int Variable;
    };
    
  • 现在想象一下你实例化A * Foo;

  • 现在假设你有一个带有这个3行函数的.lua文件:

    function Test()
        local n = Foo:Method();
        Foo.Variable = 0;
        local m = Foo.Variable;
    end
    

如何将对象A *绑定到lua,以便所有这些都可行?

伪代码,我的第一次尝试是这样的,部分来自复制粘贴的例子:

  1. 在一个只调用一次的函数中,不管A的实例数是多少:
    • 创建newmetatable(MT)
    • pushvalue(-1)(我真的没有这个)
    • setfield(-2," __ index")
    • 带有静态版本的方法的pushcfunction,它解包来自checkudata的A *指针
    • setfield(-2," Method")
  2. 在为每个实例调用的init函数中,例如富:
    • 使用newuserdata
    • 创建指向Foo的指针
    • setmetatable(MT)
    • 使用Foo设置全局,使名称可用于lua
  3. 在main中的测试函数中:
    • 使用上述.lua的3行测试函数,按全局名称
  4. 这样做时,Foo:Hide();成功调用了我的静态函数,该函数成功解压缩指针并调用其成员Hide()。

    到目前为止很好:方法()。

    然后我尝试支持.Variable访问。每个人似乎都说要再次使用metatables来覆盖__index和__newindex,并使它们成为一种通用的Get / Set,在这里你可以将某些键支持为有效的变量链接,例如: if(key ==" Variable")Variable = val;

    这也很好。

    问题是试图把这两件事放在一起。只要使用适用于Variable的getter / setter覆盖__index / __ newindex,Method()调用就不再调用Method()静态函数,而是进入你绑定的__index函数。

    所有这些都说,如何支持这种看似基本的用例组合?

    实际的代码片段比纯粹的理论喋喋不休更受欢迎。

    提醒:请仅使用基本的C API进行回复,而不是第三方的回复。

2 个答案:

答案 0 :(得分:0)

  

Method()调用不再调用Method()静态函数,但是   进入你绑定的__index函数。

所以对它进行编程,以便如果表中存在键,则首先返回,否则请使用getter / setter。

答案 1 :(得分:-2)

使用luabridgeluabind

等专用绑定

如果您手动执行此操作,最终会编写错误的副本。请提供不使用现成绑定库的正当理由?你在C ++代码中使用STL吗?

您可能还想阅读lua-users:Binding Code to Lua

使用LuaBridge:

#include <LuaBridge.h>
#include <RefCountedPtr.h>

...

struct A
{
    int Method() { return 1; }
    int Variable;
};

...

void register_my_stuff(lua_State *L) {
  luabridge::getGlobalNamespace(L)
    .beginClass<A>("A")
      .addConstructor<void (*)(), RefCountedPtr<A> >()
      .addFunction("Method", &A::Method)
      .addData("Variable", &A::Variable)
    .endClass()
  ;
}

的Lua:

function Test()
    local Foo = Core.A()
    local n = Foo:Method()
    assert ( n == 1 )
    Foo.Variable = 42;
    local m = Foo.Variable;
    assert( m == 42 )
end

Test()

无需编写自己的错误样板