lua_touserdata is returning null

1.5k Views Asked by At

I am badly stuck trying to get my userInfo reference. One of my method is returning instance of the object. Everytime createUserInfo is called, it will return the userInfoObject to the lua.

However, when I call a method for userInfo object from Lua, I am not able to get the reference of the userInfo object (lua_touserdata(L,1))

static int getUserName (lua_State *L){
   UserInfo **userInfo = (UserInfo**)lua_touserdata(L,1);

   // The following is throwing null! Need help. 
   // Not able to access the userInfo object.
   NSLog(@"UserInfo Object: %@", *userInfo);       
}

static const luaL_reg userInstance_methods[] = {
  {"getUserName", getUserName},
  {NULL, NULL}
}

int createUserInfo(lua_State *L){

  UserInfo *userInfo = [[UserInfo alloc] init];
  UserInfoData **userInfoData = (UserInfoData **)lua_newuserdata(L, sizeof(userInfo*));
  *userInfoData = userInfo;

  luaL_openlib(L, "userInstance", userInstance_methods, 0);
  luaL_getmetatable(L, "userInfoMeta");
  lua_setmetatable(L, -2);

return 1;
}

// I have binded newUserInfo to the createUserInfo method.
// I have also created the metatable for this userInfo Object in the init method.
// luaL_newmetatable(L, "userInfoMeta");
// lua_pushstring(L, "__index");
// lua_pushvalue(L, -2);
// lua_settable(L, -3);
// luaL_register(L, NULL, userInstance_methods);    

Please let me know if I am missing anything!

My LuaCode snippet:

local library = require('plugin.user')

local userInfo = library.newUserInfo()
print(userInfo.getUserName())

Update I got rid of null, after using lua_upvalueindex(1) This is giving reference back to the user info instance.

UserInfo **userInfo = (UserInfo**)lua_touserdata(L,lua_upvalueindex( 1 ));

Hope it helps others too!

2

There are 2 best solutions below

1
On

I think it may be the way your dealing with the userdata's metatable. Specifically, I think what you're returning from createUserInfo() is a table not a userdata. What I suggest is that you create the metatable once e.g. in luaopen, and then just set that on the new userdata. Something like this...

int createUserInfo(lua_State *L) {

  UserInfo *userInfo = [[UserInfo alloc] init];
  UserInfoData **userInfoData = (UserInfoData **)lua_newuserdata(L, sizeof(userInfo));
  *userInfoData = userInfo;

  luaL_getmetatable(L, "userInfoMeta");
  lua_setmetatable(L, -2);

  return 1;
}

LUALIB_API int luaopen_XXX(lua_State *L)
{
    luaL_newmetatable(L,"userInfoMeta");
    luaL_openlib(L, NULL, userInstance_methods, 0);
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
    ...
0
On

lua_upvalueindex(1) has fixed the nil error.

UserInfo **userInfo = (UserInfo**)lua_touserdata(L,lua_upvalueindex( 1 ));

I want to explain in brief on what is actually happening. function(s) in C will get stack of params passed to the method. Lua online document has example of an Array, where all of its methods take first parameter of array instance. so, lua_touserdata(L,1) worked fine as the first parameter is the array instance.

Example from lua.org shows

a = array.new(10) --size 10
array.insert(a, 1, 1) --array.insert(instance, index, value). 

lua_touserdata(L,1) works as the first param is the array instance.

In my case, I was invoking the method over instance without any params. So, the lua stack was empty in my C function and lua_touserdata(L,1) was throwing null.

Example:

a = array.new(10)
a.showValues()  --the method is not over array. it is called on instance.

So, inorder to get access to the instance in showValues, I need to call lua_touserdata(L, lua_upvalueindex(1)). This will give the array instance object.