相同用户数据的Lua数组和面向对象访问
我有一个使用C++编写的CArray类,它暴露给Lua为Array。相同用户数据的Lua数组和面向对象访问
1)创建一个新的用户数据:
int Array_new(lua_State* L)
{
int len = luaL_checkint(L, 1);
CArray<std::string> **Arr = (CArray<std::string>**)lua_newuserdata(L, sizeof(CArray<std::string>*));
*Arr = new CArray<std::string>(len);
luaL_getmetatable(L, "ArrayMetatable");
lua_setmetatable(L, -2);
return 1;
}
2)访问的元素:
int Array_getValue(lua_State* L)
{
CArray<std::string>* arr = *(CArray<std::string>**)lua_touserdata(L, 1);
int pos=luaL_checknumber(L, 2)-1;
//Omitted for brevity
lua_pushstring(L, stdStr.c_str());
return 1;
}
3)注册到Lua:
int luaopen_Array(lua_State* L)
{
luaL_newmetatable(L, "ArrayMetatable"); // metatable1
luaL_setfuncs(L, Array_metatable, 0);
lua_pushstring(L, "__index");
lua_pushvalue(L, -2); // metatable1 __index metatable1
lua_settable(L, -3); // metatable1[__index]=metatable1
/*luaL_newmetatable(L, "ArrayMetatable_2"); // metatable1 metatable2
lua_pushstring(L, "__index"); // metatable1 metatable2 __index
lua_pushstring(L, "get"); // metatable1 metatable2 __index get
lua_gettable(L, 1); // metatable1 metatable2 __index
lua_settable(L, 2);
lua_pushvalue(L, 1); //metatable1 metatable2 metatable1*/
lua_setglobal(L, "Array");
return 0;
}
问题是我不得不选择Lua代码来访问数组中的一个元素:a)arr:get(1)
获取第一个元素,b)arr[1]
获取第一个元素。
然而一个和b不同时工作,所以无论是我喜欢风格或B型。是否可以通过修改第3步同时执行a和b?
到目前为止我提供的代码在步骤2给出了一个错误,如果我尝试一个Lua表达如arr[2]
使得可变arr
的地址是0xcccccc。
您可以添加__index方法和get方法,只需单独添加它们即可。
注册函数看起来有点乱。
通常你会有两个元表 - 全局函数和成员函数。
static const struct luaL_Reg Array_globals[] = {
{ "new", Array_new },
{ NULL,NULL }
};
static const struct luaL_Reg Array_members[] = {
{ "get", Array_getValue},
{ "__index", Array_getValue },
{ NULL,NULL }
};
luaopen_函数只需要用适当的方法构建表格。 我会建议也写__len
和__setindex
int luaopen_Array(lua_State* L)
{
luaL_newmetatable(L, "ArrayMetatable"); // metatable1
luaL_setfuncs(L, Array_members, 0);
luaL_newlib(L, Array_globals);
return 1; // return table to caller.
}
我不知道我在做什么错:代替'lua_setvalue',它不存在于Lua 5.2.4中我使用了'lua_setfield'并且在最后(在返回之前)我添加了'lua_setglobal',否则这个类型不被识别。像arr [1]'这样的调用现在可以工作,但是'arr:get(1)'返回一个错误“#2到'__index'(期望的数字,得到了字符串)”。看起来这个字符串是“get” – macroland
那不是工作,'lua_pushstring(L“__index”);'实际上是压倒一切的,这将是在元表中可用的方法。如果我在代码的后面调用'luaL_setfuncs(L,Array_metatable,0);',那么索引访问将起作用,但面向对象访问不起作用。 – macroland
一旦你做对了它就会工作......你必须分别添加这两个函数。 –
事实上,我的确可以,请您张贴一些代码,以便我可以了解如何正确执行此操作。 – macroland