2

Lua 5.2 のマニュアルには、次のテキストがあります。

C 関数が作成されると、いくつかの値をそれに関連付けることができるため、C クロージャーが作成されます (lua_pushcclosure を参照)。これらの値は上位値と呼ばれ、関数が呼び出されるたびに関数にアクセスできます。

C 関数が呼び出されるたびに、その上位値は特定の疑似インデックスに配置されます。これらの疑似インデックスは、マクロ lua_upvalueindex によって生成されます。関数に関連付けられた最初の値は lua_upvalueindex(1) の位置にあり、以下同様です。lua_upvalueindex(n) へのアクセス (n は現在の関数の上位値の数よりも大きい (ただし 256 を超えない)) と、受け入れ可能な (ただし無効な) インデックスが生成されます。

そこで、「new」で作成したオブジェクトポインタに関連付けたコールバック関数を作成しました。

lua_pushstring(L,"myCallbackFunc");
Foo* ideleg = new Foo()
lua_pushlightuserdata (L, (Foo*)ideleg);
lua_pushcclosure(L, LuaCall<Tr,C,Args...>::LuaCallback,1);
lua_settable(L,-3);

そして、すべてのメカニズムは非常にうまく機能します...しかし、今度はクリーンアップの時間です。コールバック関数の登録を解除するか、プログラムを終了するときに、ポインターを削除できるように、ポインターを元に戻すことができません。

次のスニペットを使用して、テーブル エントリを見つけます。

lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
    if (lua_isstring(L, -2) && lua_tostring(L,-2) == "myCallBackFunc" ) 
    {
        // get the pointer back and delete it!
    }
}

(私はそれを使用することはできますlua_getfield(L, -1, "myCallBackFunc");か?)

しかし、関数の外側の cclosure に関連付けられた上位値を取得できませんLuaCall<Tr,C,Args...>::LuaCallback()(実際、この close 関数内では簡単に使用できますlua_upvalueindex(1)が、この場合は close 関数の外側にいます...)

この値を取得して、ポインターが不要になったときにポインターを削除する方法はありますか?


編集:必要なことを行うlua_getupvalue関数を見つけましたが、現時点では、cclosure スタック インデックスを取得する方法がわかりません。なので、まだうまくいきません。

4

1 に答える 1

4

はい、Lua でこれを行うことができます。しかし、私は強くお勧めしません。

そのコールバックにアクセスできる場合、それが Lua スタック上にある場合、Lua コードの一部がそれにアクセスできる可能性も十分にあります。つまり、破棄されると思っていても、実際には Lua が処理を完了するまでは破棄されないということです。クロージャーを破棄すると、機能しない状態になります。それでも、Lua はまだそれにアクセスできる可能性があるため、上位値を破棄した後にクロージャーが呼び出される可能性があります。

悪いことが続く。

__gcポインターを完全なユーザーデータに配置し、クリーンアップを行うメタメソッドを使用してメタテーブルをアタッチすることをお勧めします。そうすれば、実際に使用されなくなったときに確実にクリーンアップできます。

ただし、自分のやり方でやりたい場合は、いつでも を使用できますlua_getupvalue

于 2012-04-30T03:20:58.000 に答える