2

I've been having some unexpected issues with my touserdata and newuserdata, the data passed to C++ is not the same that is stored when I create the userdata, below I have all the functions related to the creation and the functions that I'm calling (

I create my avatar with this lua code avatar = avatar_create("hero1") which in c++ is this

int LuaObjectFactory::createAvatar(lua_State* L){ 
    auto avatar = new Avatar(lua_tostring(L, 1)); // 0x011afd20
    auto userdata = Util::luaP_newuserdata<Avatar>(L, avatar); // 0x011a4a18
    luaP_getScenes(L)->getActiveScene()->addEntity(avatar); 
    Util::luaP_setmetatable(L, Avatar::lGetMetatable());
    return 1;
}
template<typename T> T** luaP_newuserdata(lua_State* L, T* data){
    T** o = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
    // Does not copy the data, only remembers reference to it
    *o = data;
    return o;
}

inline void luaP_setmetatable(lua_State* L, const string& metatable){
    luaL_getmetatable(L, &metatable[0]);
    lua_setmetatable(L, -2);
}

template<typename T> T* luaP_touserdata(lua_State* L, int idx){
    return *static_cast<T**>(lua_touserdata(L, idx));
}   

then later on I try to call a function of Avatar's with this lua code

avatar = avatar_create("hero1") 
avatar:setPosition(12, 10)
avatarPos = avatar:getPosition() 

which calls these two functions

template<typename T> static int lGetPosition(lua_State* L){
    auto p = Util::luaP_touserdata<T>(L, 1); // 0x008ff0d8
    auto v = p->getPosition();
    lua_pushnumber(L, v.x);
    lua_pushnumber(L, v.y);
    return 0;
}

template<typename T> static int lSetPosition(lua_State* L){
    auto p = Util::luaP_touserdata<T>(L, 1); // 0x008ff0d8
    auto v = Math::Vector2(static_cast<int>(lua_tonumber(L, 2)),
        static_cast<int>(lua_tonumber(L, 3)));
    p->setPosition(v);
    return 0;
}

I commented the memory addresses returned from on of my attempts of debugging, the luaP_touserdata returns the same address, although even so the values that I set on 0x008ff0d8 have been erased when I go to get them later

Something else I noticed is that the address of 0x008ff0d8 is a pointer to a pointer which points back to 0x008ff0d8.

4
  • Could you check (using lua_gettop()) the number of Lua stack elements after the Util::luaP_newuserdata<Avatar> call and after the Util::luaP_setmetatable call in LuaObjectFactory::createAvatar? The implementation of Util::luaP_touserdata<T> might also be relevant ... Commented Jun 13, 2014 at 13:56
  • After new Avatar the stack returns 1, after newuserdata the stack returns 2 and after setmetatable the stack returns 3, I added the code to setmetatable above Commented Jun 13, 2014 at 14:22
  • 1
    Then add a lua_pop(L, 1); before the return 1;. Somewhere between luaP_newuserdata and the return 1 a new element is pushed to the stack (the luaP_setmetatable function looks ok, I suspect luaP_getScenes). This element is returned to Lua instead of your userdata. Commented Jun 13, 2014 at 14:39
  • I actually just found that out for myself after looking in the function that luaP_getScenes calls, I expected lua_touserdata to return and remove from stack, which it does not. The pointer is now correct, thank you Commented Jun 13, 2014 at 14:42

1 Answer 1

1

Why aren't you using a dedicated binding layer, such as luabridge or luabind? The low level problems you're struggling with in spaghetti code are effectively solved in many binding libraries.

There are even some that use modern c++, such as Selene and LuaGlue or luawrapper and luapp11

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.