尝试对本地的“testobj”(一个用户数据)进行索引,发生错误。 [./lua/addtest.lua:9]

test.exe 调用 addTest.lua 并将 lua_testobj 设置为一个 table,然后 addTest.lua 调用testobj.dll,但是 testobj.dll 无法获取 "lua_testobj"。

错误信息为

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

  1. test.exe

    L = luaL_newstate();
    // 链接lua库
    luaL_openlibs(L);
    //
    addLuaCPath( L, "./clib/?.dll" );
    //
    lua_pushlightuserdata(L, (void*)g_TestObj.get()); // g_TestObj 是全局变量
    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. addtest.lua 代码如下

    local luapath = package.path
    local cpath = package.cpath
    
    print(luapath)
    print(cpath)
    
    local testobj= require "testobj"
    
    testobj.addTest()
    
  3. testobj.dll 源代码如下

    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;
    }
    
点赞
用户234175
用户234175

看起来 testobj.dll 确实成功地将你的 lua_testobj 返回,因为你收到的错误:

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

指示 lua 将 testobj 视为 userdata。这不是问题所在;真正的问题在于你没有为该 userdata 关联任何元表,因此当脚本尝试使用它时,lua 实际上无法对其进行任何操作。

我已修改了你的 luaopen_testobj,为你的 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;
}

这应该允许你从 lua 中使用 testobj:addTest() 访问 laddTest。例如,laddtest 应该检查 testobj 是否确实是你传入的 userdata

static int laddTest(lua_State *L)
{
    auto pTestObj = reinterpret_cast<CTestObj *> (luaL_checkudata(L, 1, "lua_testobj"));
    // do something ...
    return 1;
}
2014-12-17 03:25:34
用户4273586
用户4273586

我修改了luaopen_testobj函数,在返回之前添加了lua_pop(L, 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) );

  lua_pop(L, 1);

  return 1;
}

现在,它可以正确获取pTestObj的值,不再出现“addTest.lua:9 attempt to index local 'testobj' (a userdata value)”错误。

但是我不知道错误消息的意思。

2014-12-18 02:35:46