我已经实现了一个lua包装器来使用lua中的userdata来访问C ++类:http://lua-users.org/wiki/BindingWithMembersAndMethods
我的C ++类看起来像这样:
class GameObject
{
public:
GameObject();
~GameObject();
int m_id;
float m_scale;
const char* m_path;
};
到目前为止,我可以在lua中执行此操作:
gameObject = GameObject.new()
gameObject.path = "test"
gameObject.scale = 2
local path = gameObject.path
local scale = gameObject.scale
print(scale)
print(path)
除了打印路径变量时,一切正常:
“set string”行来自我在setter函数中输入的调试:
int LuaGameObjectManager::set_string (lua_State *L, void *v)
{
v = (void*)luaL_checkstring(L, 3);
std::cout << "set string : " << (char*) v << std::endl;
return 0;
}
所以我想我正在设置正确的值,并且在使用此getter函数获取它时必须出现问题:
int LuaGameObjectManager::get_string (lua_State *L, void *v)
{
char * tmp = (char*)v;
lua_pushstring(L, tmp );
return 1;
}
这就是我如何定义我的方法和metatable:
static const luaL_Reg methodsArray[] = {
{"new", New},
{"load", load},
{0,0}
};
static const luaL_Reg metaArray[] = {
{"__gc", gc},
{"__tostring", toString},
{0, 0}
};
static LuaManager::Xet_reg_pre gettersArray[] = {
{"scale", get_int, offsetof(GameObject, m_scale) },
{"path", get_string, offsetof(GameObject, m_path) },
{0,0}
};
static LuaManager::Xet_reg_pre settersArray[] = {
{"scale", set_int, offsetof(GameObject, m_scale) },
{"path", set_string, offsetof(GameObject, m_path) },
{0,0}
};
那么有没有人知道为什么我会打印一些奇怪的值?这是编码问题吗? 我知道你们需要更多的代码来理解我的问题并帮助我,但是整个部分注册lua方法和metatable很长,所以只需告诉我你希望我发布的代码。
答案 0 :(得分:2)
我可以看到两个问题。
在函数内部分配(原始)局部变量对外界没有影响。
int LuaGameObjectManager::set_string (lua_State *L, void *v) { v = (void*)luaL_checkstring(L, 3);
v
这里是一个局部变量,所以这不会改变set_string
方法之外的任何内容。对象的内存布局如下所示:
v
\
| int | float |pointer|
\
|c|c|c|c|c|...
所以,你可能想要类似于
的东西*((char**)v) = luaL_checkstring(L, 3);
但请注意,luaL_checkstring
返回的字符串由Lua管理,并且可以在任何时候进行垃圾收集,因此您应该复制它(并且您必须清除以前的值{ {1}}或者你会得到内存泄漏)。我会把详细信息留给你......
您发布的m_path
方法(以及您在链接的Wiki文章中使用的方法)假设它正在处理内联字符数组。
get_string
您的情况不同,因为您使用指向字符数组的第一个元素的指针(参见上文)。正确的实现方式如下:
v
\
| int | float |c|c|c|c|c|...
在这种情况下,int LuaGameObjectManager::get_string (lua_State *L, void *v)
{
lua_pushstring(L, *((char**)v));
return 1;
}
已经为您制作了一份副本(最终将由Lua进行垃圾收集),因此您不必考虑这一点。