私はLuaPlusと協力して、スクリプト言語でモジュールの機能を公開してきました。そのため、LuaPlusは本当に素晴らしいですが、c ++オブジェクトを表すluaオブジェクトの削除を処理する方法がわからないため、公開されたオブジェクトのクリーンアップに固執しているため、c++リソースを正しく解放できます。
私はluaテーブルとメタテーブルを使用してcppオブジェクトを表し、cppオブジェクトへのポインターをテーブルのlightuserdataパラメーター "__object"として渡すので、次のようなことができます。
function foo()
local p = MyCppObject:new() //Create a cpp object and bind it to a table+metatable
p:do_something() //Correctly calls the cpp member function do_something
....
(exits scope) //No more references to p, so p is deleted.
end
関数の終了後(またはしばらくして)、メタテーブルメソッド "__gc"の呼び出しを取得することを期待しました。ここで、内部cppオブジェクトのdeleteを呼び出しますが、cppコールバックがで呼び出されているのがわかりません。すべて。luaの関数collectgarbageを使用してガベージコレクションを強制しようとしました。これは、luaにオブジェクトを収集させるために関数を何度も呼び出しましたが、コールバックが実行されているのがわかりません。その上、collectgarbage( "count")を呼び出した結果が時々減少するので、どこかで何かが削除されているのがわかりますが、何がわかりません。luaのドキュメントを確認しましたが、何が間違っているのかわかりません:(
コメントは大歓迎です!ありがとう!
更新:C++コード側を追加+Mudが指摘したようにローカルを追加+私のテストのサンプル
私は自分のプログラムのこの小さなサンプルを作成しました。LuaShellオブジェクトは、状態のラッパー+コマンドラインを読み取り、std::cinから読み取った文字列を実行するループです。
#include <iostream>
#include "LuaPlus.h"
class Point
{
private:
int x_,y_;
public:
Point(): x_(0), y_(0){}
Point(int a, int b): x_(a), y_(b){}
~Point() {std::cout << "Point "<< x_ << ","
<< y_ << "being deleted" << std::endl;}
int x() const { return x_;}
int y() const { return y_;}
};
LuaPlus::LuaObject metatable;
int new_point( LuaPlus::LuaState* state)
{
LuaPlus::LuaStack args(state);
//std::cout << "Creating point!!" << std::endl;
float x = 0, y = 0;
if ( args.Count() == 3)
{
if (args[2].IsNumber() && args[3].IsNumber())
{
x = args[2].GetFloat();
y = args[3].GetFloat();
}
}
Point* p = new Point(x,y);
LuaPlus::LuaObject lua_obj = state->CreateTable();
lua_obj.SetLightUserData("__object", p);
lua_obj.SetMetaTable( metatable );
return 1;
}
int my_gc_event( LuaPlus::LuaState* state)
{
std::cout << "Calling gc_event from lua" << std::endl;
return 0;
}
int main()
{
/* Creating the object that holds the Lua interpreter as well as
* the command line
*/
LuaShell::Shell shell(true);
LuaPlus::LuaObject globals = shell.get_state()->GetGlobals();
metatable = globals.CreateTable("PointMetaTable");
metatable.SetObject("__index", metatable);
metatable.Register("new", new_point);
metatable.Register("__gc",my_gc_event);
metatable.RegisterObjectDirect("x", (Point*)0 ,&Point::x);
metatable.RegisterObjectDirect("y", (Point*)0 ,&Point::y);
globals.SetObject("Point", metatable);
//Get into the read-command-line-until-quit loop.
shell.run();
return 0;
}
lua側では、これを実行してテストします。
? k,b = collectgarbage("count") print (k*1024)
> 33761
? for it=1,1000000 do foo() end
? k,b = collectgarbage("count") print (k*1024)
> 75315
? collectgarbage()
? k,b = collectgarbage("count") print (k*1024)
> 32363
ご覧のとおり、luaランタイムによると「いくらかの」ガベージコレクションがありますが、プロセスのトップレポートを見ると、メモリは上がるだけで、下がることはありません。また、ポイントデストラクタ(実際には呼び出していないため、予期されていません)または「my_gc_event」内からのメッセージ(収集ガベージ作業中のある時点で呼び出されたと思われるため、予期されていません)からのメッセージは表示されません。
再度、感謝します!