1

エクスポートされたクラス (オブジェクト) へのメンバー関数呼び出しが有効なオブジェクトに対するものであるかどうかを luabind がチェックすることは可能ですか?

luabind を使用して lua に公開された Actor というクラスがあるとします。アクター オブジェクトをパラメータとして C++ から lua 関数を呼び出しています。関数が終了する前に、スクリプトの書き込みによってアクター オブジェクトがグローバル lua 参照に配置され、後でアクセスできるようになります。

その後、アクター オブジェクトが C++ サイトから削除され、無効化されたアクター オブジェクト (そこからの任意のメソッド) にアクセスしようとする別の関数が呼び出されます。明らかに削除されているため、クラッシュ (アクセス違反) が発生します。

サンプル:

local myObjRef = nil

function doSomethingWithActor(actor)
 -- save, still valid object
 actor:Say("hello")
 myObjRef = actor
end

function calledAfterActorWasDeleted()
  --- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
  myObjRef:Say("Crash...")
end

ここでは NIL チェックは役に立ちません。これは luabinds サイトでチェックできるものですか? 関数は lua_pcall(....) を使用して実行され、スタックトレースは luabinds call.hpp results = Maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0); でエラーを示します。

そうでない場合、スクリプトを書いている人がこれらの問題を作成できないようにする別の解決策はありますか?

4

2 に答える 2

2

これで、関数が終了する前に、スクリプトの書き込みにより、アクターオブジェクトがグローバルlua参照に配置され、後でアクセスできるようになります。

その権利はあなたの問題がどこから来ているのかです。Luaコードにオブジェクトを所有させたい(つまり、このオブジェクトの存在を保持したい)場合は、Luabindメカニズムを使用して、Luabindにそれを実行するように指示する必要があります。それ以外の場合、Lua関数へのポインターを渡すと、Luabindは関数がその関数の所有権を取得しようとしないと想定します。

LuaとLuabindの間で所有権を共有boost::shared_ptrする場合は、オブジェクトをでラップし、Luabindのスマートポインターメカニズムを使用してこれを行う必要があります。

スクリプトをより適切に分離することもできます。特定のアクターを操作するスクリプトがある場合は、そのスクリプトとそれに含まれるすべての関数をオブジェクトとともに破棄する必要があります(つまり、スクリプトへのすべての参照を失う)。これには、C++側での適切なコーディング規律が必要です。また、Lua環境を使用して、スクリプトの各インスタンスを適切にカプセル化する必要があります。これにより、グローバルを介して物事をこっそり持ち出すことができなくなります。最後に、スクリプトが呼び出されるタイミングと呼び出されないタイミングをC++で完全に制御する必要があります。

それ以外の場合、所有権は、スクリプト作成者が単に知って注意しなければならないものです。C++パラメーターを古いLua値のように扱うことはできません。


規律あるプログラミングの練習が不可能または実用的でない場合は、Luaに実際のC++オブジェクトを渡さないようにする必要があります。代わりに、元のオブジェクトへの参照であるプロキシオブジェクトをLuaに渡す必要があります。boost :: weak_ptrは、そのようなオブジェクトの良い例です(ただし、Luaに正確に渡すことはできません)。プロキシは、呼び出しを実際のオブジェクトに転送します。オブジェクトが削除されている場合、プロキシはこれを検出して失敗するか、何もしません。

于 2013-01-25T22:46:20.023 に答える
0

次の方法で問題を解決しました。

オブジェクトを削除しようとすると、C++ のすべての lua 関数を反復処理します (リストにそれらがあり、それぞれが特定のアクター オブジェクトにバインドされています)。次に、各上位値 (関数にアクセス可能なグローバル/ローカル変数) を調べます。次に、ユーザーデータ ポインターと削除しようとしているオブジェクトを比較します。それらが一致し (およびそのクラス)、上位値が NIL の場合。必要に応じて、とにかくうまく機能しないため、その問題のある機能を削除することもできます。

そのため、次に関数が呼び出されたときに、「xxx a nil 値にアクセスしようとしています...」というソフト lua エラーが発生するだけです。アクセス違反はもうありません。

I know people would say "dont use lua_getupvalue/lua_setupvalue - they are only for debugging!" - but there is actually no documented or spoken side effect - and in my case its perfectly safe and works well - also there isnt the issue with left over proxy objects i could not delete.

于 2013-01-31T11:05:12.397 に答える