3

C++ オブジェクトを lua に返すには?

私のC++コードは次のとおりです。

class MyClass
{
public:
  void say()
  {
    print("Hello\r\n");
  }
};

int test(lua_State* l)
{
  MyClass* obj = new MyClass();
  lua_pushlightuserdata(l, obj);
  return 1;
}

Lua テストは次のとおりです。

local a = MyClass:new()
a:say()  <--- OK, beacause I set metatable!!
local b = test()
b:say()  <--- ERROR: attempt to index local 'b' (a userdata value)

test() 関数を変更して正常に動作させるには?
obj は lua によって自動破棄されますか?

PS: MyClass メタテーブルを次のように設定しました

void l_registerClass()
{
  lua_newtable(l);
  int methods = lua_gettop(l);
  luaL_newmetatable(l, "MyClass");
  int metatable = lua_gettop(l);
  lua_pushvalue(l, methods);
  lua_setglobal(l, "MyClass");

  lua_pushvalue(l, methods);  
  l_set(l, metatable, "__metatable");

  //set metatable __index
  lua_pushvalue(l, methods);
  l_set(l, metatable, "__index");

  //set metatable __gc
  lua_pushcfunction(l, l_destructor);  
  l_set(l, metatable, "__gc");

  //set method table
  lua_newtable(l);                // mt for method table  
  lua_pushcfunction(l, l_constructor);  
  lua_pushvalue(l, -1);           // dup new_T function  
  l_set(l, methods, "new");         // add new_T to method table  
  l_set(l, -3, "__call");           // mt.__call = new_T  
  lua_setmetatable(l, methods);  

  // set methods metatable   
  lua_pushstring(l, "say");
  lua_pushcclosure(l, l_proxy, 1);  
  lua_settable(l, methods);

  lua_pop(l, 2);
}

int l_proxy(lua_State* l)
{
  int i = (int)lua_tonumber(l, lua_upvalueindex(1));
  lua_remove(l, 1);  // remove self so member function args start at index 1
  //call real function
  MyClass* obj = getInstance();
  obj->say();
  return 1;
}

私はステップを失うべきではありませんか?
Lua バインディング フレームワークは使用せず、純粋な Lua ライブラリを使用しています。

====更新1 ====

user1520427 さんの回答ありがとうございます。

int test(lua_State* l)
{
  MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
  *c = new MyClass();       // we manage this
  lua_getglobal(l, "MyClass");
  lua_setmetatable(l, -2);
  return 1;
}

Luaでテストします

local b = test()
print( type(b) )
local meta = getmetatable(b)
for k,v in pairs(meta) do
  print("    ", k, v)
end

Lua show metatable は正しいです。

userdata
  say     function: 00602860
  new     function: 00493665

しかし、luaはまだ同じエラーを表示します

b:say()   <-- attempt to index local 'b' (a userdata value)

===更新2 ===

int test(lua_State* l)
{
  MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
  *c = new MyClass();       // we manage this
  luaL_getmetatable(l, "MyClass");  //
  lua_getglobal(l, "MyClass");
  lua_setmetatable(l, -2);
  return 1;
}

ルアテスト結果:

b:say()   <-- attempt to call method 'say' (a nil value)

=== 更新 3 ===

int test(lua_State* l)
{
  MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
  *c = new MyClass();       // we manage this
  luaL_getmetatable(l, "MyClass");  
  luaL_setmetatable(l, "MyClass");  //modify
  return 1;
}

Lua テスト結果:

b:say()   <-- calling 'say' on bad self
4

2 に答える 2

1

test返されたものを登録したクラスに関連付けていません。次のようなものを試してください:

int test(lua_state* l) { 
  MyClass** c = lua_newuserdata(l, sizeof(MyClass*)); // lua will manage the MyClass** ptr
    *c = new MyClass(); // we manage this
    luaL_getmetatable(l, "MyClass");
    lua_setmetatable(l, -2);
    return 1;
}

それは私の頭のてっぺんから外れていますが、あなたはその考えを理解しています。すでにデストラクタを設定しているため、Lua ガベージ コレクションがユーザーデータを収集すると、__gcfunc が呼び出され、データのキャスト、逆参照、および削除が行われます。

于 2013-01-31T06:00:37.113 に答える
0

user1520427 に感謝します。lhf の
正しいコードは次のとおりです。

int test(lua_State* l)
{
  MyClass** c = (MyClass**)lua_newuserdata(l, sizeof(MyClass*));
  *c = new MyClass();       // we manage this
  luaL_setmetatable(l, "MyClass");  //assign MyClass metatable
  return 1;
}

Lua テスト コードは問題なく動作します。

于 2013-01-31T15:08:43.360 に答える