4

C++ プログラムにユーザーデータとして Lua に渡すオブジェクトがあり、このユーザーデータのメタテーブルをオーバーライドして、(__newindex および __index を介して) オブジェクトのインデックスとの間で代入を行うと、代入を変換する C が呼び出されるようにします。 C++ オブジェクトに影響を与えるか、C++ 要素を Lua 値 (別のユーザーデータまたは bool、number、string などの基本型) に変換します。ユーザーデータは、C++ プログラムから呼び出されるイベントのような Lua 関数に引数として渡されます。

luaL_newmetatable(L, "object");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);  /* pushes the metatable */
lua_settable(L, -3);  /* metatable.__index = metatable */

luaL_openlib(L, NULL, vallib_m, 0);
luaL_openlib(L, "internal", vallib_f, 0);

lua_pushstring(L, "__index");
lua_pushstring(L, "get");
lua_gettable(L, 2);  /* get val.get */
lua_settable(L, 1);  /* metatable.__index = val.get */

lua_pushstring(L, "__newindex");
lua_pushstring(L, "set");
lua_gettable(L, 2); /* get array.set */
lua_settable(L, 1); /* metatable.__newindex = val.set */

ただし、これにより、実際の変数自体を割り当てることはできず、変数のインデックスのみを割り当てることができます。代入演算子を直接オーバーライドするためのメタイベントがないため、回避策を探しています。

言い換えれば、私はこれを行うことができます:lua_userdata_object_passed_as_arg_to_event["is_it_true"]=true そして、Lua ブール値を内部 C++ オブジェクトに割り当てますが、これを行うと: lua_userdata_object_passed_as_arg_to_event = new_object() Lua 変数が参照するものは変更されますが、私が理解しているように、コア オブジェクトには何もしません。それ。

私が検討した回避策の 1 つは、開発者がlua_userdata_object_passed_as_arg_to_event["__self"] = new_object() オブジェクト自体を変更したい場合に行う必要のあるハックですが、これは望ましくありません。

そのため、グローバル変数を使用して代入演算子をオーバーライドし、グローバルなメタテーブル代入演算子をオーバーライドする独自の解決策をいくつか見つけましたが、誰かがこの解決策を説明するのを手伝ってくれるかどうかを探しています。http://lua-users.org/lists/lua-l/2012-01/msg00413.htmlおよびhttps://www.lua.org/pil/14.2.htmlを参照してください。特に、変数はグローバルではなく関数の引数なので、C API を介してグローバルに変換し、グローバル ユーザーデータに対して割り当てが行われた場合にアクションを実行するカスタム C 関数によって割り当てがキャプチャされるようにするにはどうすればよいでしょうか?

ちなみに、私のユーザーデータはオブジェクトへのポインターであり、それが問題になる場合は、大きなオブジェクトの複製を回避します。

4

1 に答える 1

5

Lua と C/C++ は、異なるニーズを持つ異なる言語です。C/C++ では、変数は常に特定のオブジェクトを参照します。このオブジェクトの内容を変更することはできますが、別のオブジェクトを扱う変数を作成することはできません。その場合、 の値をにa = b;コピーしています。話しているオブジェクトを変更することはできません。baa

Lua では、変数は永続的に何も参照しません。したがって、変数が現在保持しているオブジェクトとそのオブジェクトの値には違いがあります。

グローバル変数機能を介したあなたのクラッジは機能しますが、local変数は実際には存在しないものです。これらは Lua スタック上の場所です。それらに関して Lua のデフォルトの動作をオーバーライドすることはできません。

これを処理する最善の方法は、C と Lua の違いを受け入れることです。Lua でコードを記述するのと同じように、Lua でコードを記述します。Lua コードを C のように動作させようとしないでください。そのやり方は愚かです。それらは異なる言語であり、それらの違いに反対するのではなく、それらの違いを受け入れる必要があります。

Lua に と同等の機能を与えたい場合は、オブジェクトの値に代入できるように、または何かとa = b呼ばれる型で関数を作成する必要があります。assignすべてのテーブル要素をあるテーブルから別のテーブルにコピーする場合と同様に、それを行う関数を作成する必要があります。

于 2016-08-16T19:11:03.363 に答える