2

test.exe call addTest.lua and set the lua_testobj to the table, and addTest.lua call testobj.dll, but testobj.dll can not get the "lua_testobj"

error msg is

addTest.lua:9 attempt to index local 'testobj' (a userdata value)

  1. test.exe

    L = luaL_newstate();
    // link lua lib
    luaL_openlibs(L);
    //
    addLuaCPath( L, "./clib/?.dll" );
    //
    lua_pushlightuserdata(L, (void*)g_TestObj.get()); // g_TestObj is a global vars
    lua_setfield(L, LUA_REGISTRYINDEX, "lua_testobj");
    // 
    int err = 0;
    err = luaL_loadfile( L, "./lua/addTest.lua" );
    if( err != LUA_OK )
      printf("Failed to load addTest.lua![%s]", lua_tostring(L,-1));
    
    err =  lua_pcall( L, 0, 1, 0 );
    if( err != LUA_OK )
      printf("Failed to call addTest.lua![%s]", lua_tostring(L,-1));
    
  2. the addtest.lua code is following

    local luapath = package.path
    local cpath = package.cpath
    
    print(luapath)
    print(cpath)
    
    local testobj= require "testobj"
    
    testobj.addTest()
    
  3. and the testobj.dll source code is following

    static int laddTest(lua_State *L)
    {
      lua_getfield(L, LUA_REGISTRYINDEX, "lua_testobj");
      return 1;
    }
    
    extern "C" int __declspec(dllexport) 
    luaopen_testobj(lua_State *L)
    {
      luaL_Reg l[] = {
        { "addTest", laddTest },
        { NULL, NULL },
      };
    
      luaL_checkversion(L);
      luaL_newlib(L,l);
    
      lua_getfield(L, LUA_REGISTRYINDEX, "lua_testobj");
      CTestObj* pTestObj = static_cast<CTestObj*>( lua_touserdata(L,-1) );
    
      return 1;
    }
    
greatwolf
  • 20,287
  • 13
  • 71
  • 105
Sleepwom
  • 227
  • 6
  • 15

2 Answers2

1

It looks like testobj.dll did actually return your lua_testobj successfully because the error you're getting:

addTest.lua:9 attempt to index local 'testobj' (a userdata value)

indicates lua sees testobj as a userdata. That's not where the problem is; the real issue is that you didn't associate any metatable with that userdata so lua can't really do anything with it when a script tries to use it.

I've modified your luaopen_testobj to create and register a metatable for your testobj:

extern "C" int __declspec(dllexport) 
luaopen_testobj(lua_State *L) 
{
  luaL_Reg l[] = 
  {
      { "addTest", laddTest },
      { NULL, NULL },
  };

  luaL_checkversion(L);
  lua_pushlightuserdata(L, (void*)g_TestObj.get());

  // g_TestObj, testobj_mt, {l}
  luaL_newmetatable(L, "lua_testobj");
  luaL_newlib(L, l);
  // testobj_mt.__index = {l}
  lua_setfield(L, -2, "__index");

  // return setmetatable(g_TestObj, testobj_mt)
  lua_setmetatable(L, -2);
  return 1;
}

This should allow you to access laddTest using testobj:addTest() from lua. laddtest should check that testobj is indeed the userdata you passed in, for example:

static int laddTest(lua_State *L)
{
    auto pTestObj = reinterpret_cast<CTestObj *> (luaL_checkudata(L, 1, "lua_testobj"));
    // do something ...
    return 1;
}
greatwolf
  • 20,287
  • 13
  • 71
  • 105
  • but I want to pass the g_TestObj from exe to dll – Sleepwom Dec 17 '14 at 03:40
  • In that case, you'll have to move the metatable registration code over to `test.exe`'s `main`. Just make sure the metatable is added to the registry once. – greatwolf Dec 17 '14 at 03:57
  • You can also have `luaopen_testobj` just return a new luatable containing the functions in `luaL_Reg l[]` which would simplify some things since the script won't deal with the lightudata directly. But it's unclear what your end goal is so I can't recommend one over the other. – greatwolf Dec 17 '14 at 04:06
0

I've modified the luaopen_testobj function, add lua_pop(L, 1); before return

extern "C" int __declspec(dllexport) 
luaopen_testobj(lua_State *L)
{
  luaL_Reg l[] = {
    { "addTest", laddTest },
    { NULL, NULL },
  };

  luaL_checkversion(L);
  luaL_newlib(L,l);

  lua_getfield(L, LUA_REGISTRYINDEX, "lua_testobj");
  CTestObj* pTestObj = static_cast<CTestObj*>( lua_touserdata(L,-1) );

  lua_pop(L, 1);

  return 1;
}

Now, it can correctly to obtain the value of pTestObj, no longer appear "addTest.lua:9 attempt to index local 'testobj' (a userdata value)" wrong.

But I don't know what's the meaning of the error message

Sleepwom
  • 227
  • 6
  • 15
  • As I already explained in my answer, userdata isn't indexable without a metatable because it's C/C++ data. – greatwolf Dec 18 '14 at 06:43