如何注册c++嵌套类到Lua
How to register C++ nested class to Lua
我目前能够将c++类绑定到Lua,包装在我使用luaL_requiref
加载的模块中,其中包含适当的静态开放函数,用于luaL_newmetatable
, luaL_setfuncs
等处理。伟大的工作。
但是如果我想绑定一个嵌套类呢?
考虑下面的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_requiref
进行另一次调用,或者我可以在单个luaL_requiref
中进行调用?
谢谢!
编辑:好的,现在这是一个完全不同的问题。
可以,您可以在一个电话中完成。
luaL_requiref
函数只是简单地调用传递的函数,例如检查模块是否尚未加载(并更新package.loaded
表),注册相应的全局值等。
我假设您不想在没有Bar
的情况下从Foo
或Foo
单独加载Bar
,因此package.loaded
中的单个"Foo"
条目应该足够了。同样,也不需要全局Bar
变量。
所以,简单地把它作为你的Foo
的一个字段,就是这样。
注:确保你的析构函数被调用:通常,如果你使用lua_newuserdata
和位置new,你需要使用__gc
元方法。
EDIT2:修改luaopen_Foo方法(注意__call
,而不是__index
的构造函数)。我个人更喜欢new
用于此目的,但如果您想将它们创建为local f = Foo()
,那么您需要__call
):
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
}
如果你曾经好奇过,luaL_requiref函数(带有一些伪代码):
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
}
}
注意区别:luaL_requiref
从Lua内调用你的函数,这确保了执行后适当的堆栈清理,例如,你可以把一些垃圾放在那里,你唯一要确保的是你的顶层值是你想要的结果与return 1;
一起。但是,如果直接调用该函数,就没有这种奢侈了。所以要确保它只在堆栈顶部添加一个值
- 嵌套在类中时无法设置成员数据
- 无法访问嵌套类.类的使用无效
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 在C++中搜索嵌套多映射值
- 在C++中将矢量转换为嵌套地图
- C++嵌套if语句,基本货币交换
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 嵌套的匿名命名空间
- 了解嵌套循环打印星号图案
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 嵌套for循环C++的问题(初学者)
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 用C#中的并集模拟C++嵌套结构
- 部分专业化和嵌套模板
- 我是否正确地将嵌套的 lua 表作为 C 函数的参数
- Lua C API嵌套表seg.的错
- 将嵌套表从Lua传递到C
- 如何注册c++嵌套类到Lua