Reputation: 491
i have implemented a lua wrapper to access a C++ class using userdata in lua following this article : http://lua-users.org/wiki/BindingWithMembersAndMethods
My C++ class looks like this :
class GameObject
{
public:
GameObject();
~GameObject();
int m_id;
float m_scale;
const char* m_path;
};
So far i can do this in lua:
gameObject = GameObject.new()
gameObject.path = "test"
gameObject.scale = 2
local path = gameObject.path
local scale = gameObject.scale
print(scale)
print(path)
Everything works fine except when printing the path variable :
The "set string" line comes from a debug i put in the setter function :
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;
}
So i guess i'm setting the right value and the issue must occur when getting it with this getter function :
int LuaGameObjectManager::get_string (lua_State *L, void *v)
{
char * tmp = (char*)v;
lua_pushstring(L, tmp );
return 1;
}
And this is how i define my methods and 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}
};
So does anyone have an idea of why i'm printing some weird values ? is this an encoding issue ? I know you guys will need more code to understand my problem and to help me but the whole part to register the lua methods and metatable is pretty long so just tell my what code you would want me to post.
Upvotes: 1
Views: 325
Reputation: 4271
I can see two problems.
Assigning to a (primitive) local variable inside of a function has no effect on the outside world.
int LuaGameObjectManager::set_string (lua_State *L, void *v) { v = (void*)luaL_checkstring(L, 3);
v
is a local variable here, so this doesn't change anything outside of the set_string
method. The memory layout of your object looks like this:
v
\
| int | float |pointer|
\
|c|c|c|c|c|...
So, you probably want something similar to
*((char**)v) = luaL_checkstring(L, 3);
But be aware that the string that luaL_checkstring
returns is managed by Lua and can be garbage-collected at any point, so you should make a copy of it (and you have to clean up the previous value of m_path
or you'll get a memory leak). I'll leave the details to you ...
The get_string
method you posted (and that is used in the wiki article you linked) assumes it is working on an inline character array.
v
\
| int | float |c|c|c|c|c|...
Your case is different as you are using a pointer to the first element of a character array (see above). A proper implementation would look like:
int LuaGameObjectManager::get_string (lua_State *L, void *v)
{
lua_pushstring(L, *((char**)v));
return 1;
}
In this case lua_pushstring
already makes a copy for you (that will be garbage-collected by Lua eventually), so you don't have to think about that.
Upvotes: 2