如何注册C++;将类嵌套到Lua 我目前可以将C++类绑定到Lua中,它封装在使用 LualuRealFuff>代码>的模块中,具有适当的静态打开函数,可以执行 LualueNeMeTabase、 LualuStEngsSuffs等。效果很好

如何注册C++;将类嵌套到Lua 我目前可以将C++类绑定到Lua中,它封装在使用 LualuRealFuff>代码>的模块中,具有适当的静态打开函数,可以执行 LualueNeMeTabase、 LualuStEngsSuffs等。效果很好,c++,lua,C++,Lua,但是如果我想绑定一个嵌套类呢 考虑下面的C++代码: class Foo { public: Foo(){} void do_something(); class Bar { public: Bar(){} void do_something_else(); }; }; 以及Lua注册: int foo_new(lua_State* L) { new(lua_newuserdata(L, sizeof(foo))

但是如果我想绑定一个嵌套类呢

考虑下面的C++代码:

class Foo {
public:
    Foo(){}
    void do_something();

    class Bar {
    public:
        Bar(){}
        void do_something_else();
    };
};
以及Lua注册:

int foo_new(lua_State* L) {
    new(lua_newuserdata(L, sizeof(foo)))foo();
    luaL_setmetatable(L, "Foo");
    return 1;
}
int foo_do_something(lua_State* L) {
    Foo* foo = (Foo*)luaL_checkudata(L, 1, "Foo");
    foo->do_something();
    return 0;
}
int luaopen_foo(lua_State* L) {
    const luaL_Reg functions[] = {
        {"__index", foo_new},
        {"do_something", foo_do_something},
        {nullptr, nullptr}
    };
    if( luaL_newmetatable(L, "Foo") ) {
        luaL_setfuncs(L, functions, 0);
        lua_pushvalue(L, -1);
        lua_setfield(L, -2, "__index");
    }
    return 1;
}

...

luaL_requiref(L, "Foo", luaopen_foo, 1);
我可以在Lua中访问
Foo::do_something()
,例如:

foo = Foo()
foo:do_something()
现在的问题是:我如何在Lua中注册
Foo::Bar
嵌套类,以便可以这样访问它:

bar = Foo.Bar()
bar:do_something_else()
本质上,我想在
Foo
元表中注册
Bar
方法,而不是全局注册。我是否需要再次调用
luaL\u requiref
,或者我可以在单个
luaL\u requiref
中执行此操作


谢谢大家!

编辑:好的,现在这是一个完全不同的问题

是的,你可以在一个电话里完成

luaL\u requiref
函数只是用铃铛和哨子调用传递的函数,例如检查模块是否尚未加载(并更新
package.loaded
表),注册相应的全局值等

我假设您不想在没有
条形码的情况下将
条形码
Foo
Foo
分开加载,因此
包中的一个
“Foo”
条目就足够了。同样,不需要全局
变量

所以,简单地把它作为
Foo
的一个字段,就是它

另外,请确保调用过析构函数:通常,如果将
lua\u newuserdata
与placement new一起使用,则需要使用
\uu gc
元方法

EDIT2:修改你的luaopen\u Foo方法(注意
\u调用
,而不是构造函数的
\u索引
。我个人更喜欢
新建
,但是如果你想将它们创建为
本地f=Foo()
,那么你需要
\u调用
):

如果您曾经好奇过,luaL_requiref函数(带有一些伪代码)是什么:


请注意区别:
luaL_requiref
从Lua内部调用函数,这样可以确保在其执行后正确清理堆栈,例如,您可以将一些垃圾放在那里,唯一需要确保的是您的顶级值是您想要的结果,同时
返回1。但是,如果您直接调用该函数,您就没有这种奢侈了。因此,确保它只在堆栈顶部添加一个值。

编辑:好的,现在这是一个完全不同的问题

是的,你可以在一个电话里完成

luaL\u requiref
函数只是用铃铛和哨子调用传递的函数,例如检查模块是否尚未加载(并更新
package.loaded
表),注册相应的全局值等

我假设您不想在没有
条形码的情况下将
条形码
Foo
Foo
分开加载,因此
包中的一个
“Foo”
条目就足够了。同样,不需要全局
变量

所以,简单地把它作为
Foo
的一个字段,就是它

另外,请确保调用过析构函数:通常,如果将
lua\u newuserdata
与placement new一起使用,则需要使用
\uu gc
元方法

EDIT2:修改你的luaopen\u Foo方法(注意
\u调用
,而不是构造函数的
\u索引
。我个人更喜欢
新建
,但是如果你想将它们创建为
本地f=Foo()
,那么你需要
\u调用
):

如果您曾经好奇过,luaL_requiref函数(带有一些伪代码)是什么:


请注意区别:
luaL_requiref
从Lua内部调用函数,这样可以确保在其执行后正确清理堆栈,例如,您可以将一些垃圾放在那里,唯一需要确保的是您的顶级值是您想要的结果,同时
返回1。但是,如果您直接调用该函数,您就没有这种奢侈了。因此,请确保它只在堆栈顶部添加一个值。

您已经成为几代人的草率术语的受害者。虽然
Bar
看起来有点“sub”,但它根本不是一个子类。它是一个嵌套类。我们更喜欢技术术语“基类”、“派生类”和“成员类型”,它们不容易被误解。你已经成为了几代人的草率术语的受害者。虽然
Bar
看起来有点“sub”,但它根本不是一个子类。它是一个嵌套类。我们更喜欢技术术语“基类”、“派生类”和“成员类型”,它们不容易被误解。好吧,我承认我写这篇文章很快-我删除了
静态
关键字。问题不在于在Lua中实例化类是否有用。它特别是关于使用
luaL_requiref
注册class.Edited。你需要更详细的信息吗?我设置了全局析构函数等等,只是想把代码缩写一下。现在,我需要调用哪些函数才能将
Bar
注册为您所说的字段?由于某种原因,我无法让它工作。更新。现在对你有好处吗?谢谢你澄清了我的问题所在!现在它就像一个符咒!好吧,我承认我写这篇文章很快-我删除了
static
关键字。问题不在于在Lua中实例化类是否有用。它特别是关于使用
luaL_requiref
注册class.Edited。你需要更详细的信息吗?我设置了全局析构函数等等,只是想把代码缩写一下。现在,我需要调用哪些函数才能将
Bar
注册为您所说的字段?由于某种原因,我无法让它工作。更新。有什么好处吗
int luaopen_foo(lua_State* L) 
{
    static const luaL_Reg functions[] = 
    {
        {"__call"       , foo_new},
        {"do_something" , foo_do_something},
        {nullptr        , nullptr}
    };

    if (luaL_newmetatable(L, "Foo")) 
    {
        luaL_setfuncs(L, functions, 0);
        lua_pushvalue(L, -1);
        lua_setfield(L, -2, "__index");

        // =================
        // Here, your "Foo" metatable is on top of your stack
        // about to be returned as the result of your luaopen_Foo.
        // Simply put another table above and set if as a Foo.Bar
        if (luaopen_FooBar(L))
            lua_setfield(L, -2, "Bar");
    }
    return 1;
}

int luaopen_FooBar(lua_State * L)
{
    static const luaL_Reg functions[] = 
    {
        {"__call"            , foo_bar_new},
        {"do_something_else" , foo_bar_do_something_else},
        {nullptr             , nullptr}
    };

    // luaL_newmetatable puts its result on top of the stack
    // - exactly what we want for lua_setfield
    if (luaL_newmetatable(L, "Foo::Bar"))
    {
        luaL_setfuncs(L, functions, 0);
        lua_pushvalue(L, -1);
        lua_setfield(L, -2, "__index");
    }
    return 1; // Indicate the result is on top of the stack
}
void luaL_requiref(lua_State *L, const char *name, lua_CFunction openf, int set_global) 
{
    if (!try_get_already_loaded_module(modname))
    {
        lua_pushcfunction(L, openf); // Call the openf function
        lua_pushstring(L, modname);  // with modname as its argument
        lua_call(L, 1, 1);

        memorize_the_result_for_future(modname);
    }
    if (set_global)
    {
        lua_pushvalue(L, -1);       // copy the module
        lua_setglobal(L, modname);  // set _G[modname] = module
    }
}