绑定C++;指向Lua的向量 我试图手动将C++中的指针向量绑定到Lua。
我仅限于一个部分支持C++11的编译器,因此无法使用现有的绑定库,因为它们现在似乎都使用C++17 例如,我有一个类,其中包含指向子类的指针列表。从Lua的角度来看,子向量是只读的-我不需要添加、删除等。只需阅读即可绑定C++;指向Lua的向量 我试图手动将C++中的指针向量绑定到Lua。,c++,lua,C++,Lua,我仅限于一个部分支持C++11的编译器,因此无法使用现有的绑定库,因为它们现在似乎都使用C++17 例如,我有一个类,其中包含指向子类的指针列表。从Lua的角度来看,子向量是只读的-我不需要添加、删除等。只需阅读即可 class Child { public: std::string name; }; class Parent { public: std::vector <Child *>children; }; ... Parent parent;
class Child
{
public:
std::string name;
};
class Parent
{
public:
std::vector <Child *>children;
};
...
Parent parent;
Child * m = new Child;
m->name = "Mary";
parent.children.push_back(m);
Child * b = new Child;
b->name = "Bob";
parent.children.push_back(b);
...
父绑定
static int Parent_count(lua_State * lua) {
// used by both the Parent function and metatable __len
lua_pushinteger(lua, parent.children.size());
return 1;
}
static int Parent_children(lua_State * lua)
{
// stack -1=number(1)
int idx = lua_tonumber(lua, -1);
Child ** c = static_cast<Child **>(lua_newuserdata(lua, sizeof(Parent *)));
*c = parent.children[idx];
luaL_getmetatable(lua, "ChildMetaTable"); // [-0, +1, m]
lua_setmetatable(lua, -2);
// return new userdata - does not work
return 1;
}
static const struct luaL_Reg Parent_FunctionList[] = {
{ "count", Parent_count },
{ "children", Parent_children },
{ NULL, NULL }
};
static int Parent_tostring(lua_State * lua) {
lua_pushstring(lua, "Parent");
return 1;
}
static int Parent_index(lua_State * lua) {
// stack -1=number(1) -2=table
int idx = lua_tonumber(lua, -1);
Child * c = parent.children[idx];
// what to return here?
return 0;
}
static const struct luaL_Reg Parent_MetaList[] = {
{ "__tostring", Parent_tostring },
{ "__len", Parent_count },
{ "__index", Parent_index },
{ NULL, NULL }
};
void Parent_Register(lua_State * lua) {
luaL_newlib(lua, Parent_FunctionList);
if(luaL_newmetatable(lua, "ParentMetaTable"))
luaL_setfuncs(lua, Parent_MetaList, 0);
lua_setmetatable(lua, -2);
lua_setglobal(lua, "Parent");
}
但是试图接近孩子们也不管用
>c = Parent[1]
>print(c)
Child
>print(type(c))
userdata
>print(c.name())
[string "main"]:8: attempt to index a ChildMetaTable value (global 'c')
我迷失在Parent\u index
中,在这里我需要一个指向C Parent对象的指针,而不是Lua表。我理解这个方法是使用userdata或lightuserdata,但不知道如何将类绑定到Lua来实现这一点。子绑定也是如此,它生成一个ChildMetatable,但没有Lua表
编辑:我在父项下添加了一个children函数,但仍然不起作用。还将lua_setmetatable
的一些索引从堆栈底部更改为堆栈顶部(负数)
Edit2:这是因为我试图让Parent:children同时充当表和用户数据。因此,我可以使用C对象指针返回userdata,同时返回带有_索引的ChildMetaTable,以确定如何处理子方法。我试图做的是同时拥有Lua表和userdata 首先,最好用表中为子对象创建新用户数据的函数替换父
\u index
方法
static int Parent_children(lua_State * lua)
{
int idx = luaL_checkinteger(lua, -1);
Parent * p = &parent;
luaL_argcheck(lua, (idx >= 0) && (idx < (int)p->children.size()), 1, "index out of range");
Child ** pc = static_cast<Child **>(lua_newuserdata(lua, sizeof(Child *)));
*pc = parent.children[idx];
luaL_getmetatable(lua, "ChildMetaTable"); // [-0, +1, m]
lua_setmetatable(lua, -2);
return 1;
}
static const struct luaL_Reg Parent_MetaList[] = {
{ "__tostring", Parent_tostring },
{ NULL, NULL }
};
子方法从userdata中获取一个C指针
static int Child_name(lua_State * lua)
{
Child * c = *reinterpret_cast<Child **>(luaL_checkudata(lua, -1, "ChildMetaTable"));
lua_pushstring(lua, c->name.c_str());
return 1;
}
这可能不是最佳解决方案,但正朝着这个方向发展
编辑:
全局父级
可以在展开的luaL_newlib
宏中作为upvalue传递,而不是使用全局父级
luaL_newlibtable(lua, Parent_FunctionList);
lua_pushlightuserdata(lua, parent);
luaL_setfuncs(lua, Parent_FunctionList, 1);
...
static int Parent_children(lua_State * lua) {
Parent * parent= (Parent *)(lua_topointer(lua, lua_upvalueindex(1)));
...
您应该在
Parent\u count
中使用lua\u pushinteger
而不是lua\u pushnumber
,因为使用浮点数作为计数是很奇怪的。您可能不想在Parent\u index
中使用lua\u pushlightuserdata
,因为轻用户数据没有元表。您需要使用lua\u newuserdatauv
创建完整的元数据。谢谢。我已更改为lua\u pushinteger
,还更改了lua\u setmetatable
以使用堆栈顶部的索引。我尝试过创建userdata,然后在Parent\u children
中设置元表,但仍然没有。
static int Child_index(lua_State * lua)
{
const char * fn_name = luaL_checkstring(lua, -1);
for(const luaL_Reg * fn = Child_FunctionList; fn->name != NULL; fn++)
{
if(strcmp(fn_name, fn->name) == 0)
{
lua_pushcfunction(lua, fn->func);
return 1;
}
}
return 0;
}
static const struct luaL_Reg Child_MetaList[] = {
{ "__tostring", Child_name },
{ "__index", Child_index },
{ NULL, NULL }
};
static int Child_name(lua_State * lua)
{
Child * c = *reinterpret_cast<Child **>(luaL_checkudata(lua, -1, "ChildMetaTable"));
lua_pushstring(lua, c->name.c_str());
return 1;
}
void Child_Register(lua_State * lua)
{
if(luaL_newmetatable(lua, "ChildMetaTable"))
luaL_setfuncs(lua, Child_MetaList, 0);
lua_pop(lua, 1);
}
luaL_newlibtable(lua, Parent_FunctionList);
lua_pushlightuserdata(lua, parent);
luaL_setfuncs(lua, Parent_FunctionList, 1);
...
static int Parent_children(lua_State * lua) {
Parent * parent= (Parent *)(lua_topointer(lua, lua_upvalueindex(1)));
...