しばらく頭を包み込もうとしていますが、本当に理解できるチュートリアルや説明が見つからないようです。
なぜそれらが必要なのですか、なぜC関数をLuaメタテーブルに直接バインドできないのですか?
Userdataは、任意のサイズとコンテンツのガベージコレクションされた値です。 lua_newuserdata()
を使用してC APIから作成します。これにより、スタックに作成およびプッシュされ、Cから適切と思われるように初期化するコンテンツへのポインターが提供されます。
これは、malloc()
の呼び出しに非常に似ています。 malloc()
との主な違いは、free()
を呼び出す必要がないことです。代わりに、最後の参照を蒸発させるだけで、ガベージコレクターは最終的にストレージを再利用します。
これらは、Cから有用であるが、Luaから管理する必要があるデータを保持するのに最も役立ちます。これらは、CまたはC++オブジェクトをLuaにバインドできるようにする重要な機能である個々のメタテーブルをサポートします。ユーザーデータのコンテンツにアクセス、変更、使用するCで記述されたメソッドをメタテーブルに入力するだけで、Luaからアクセスできるオブジェクトが作成されます。この良い例は io
library です。これは、C _FILE *
_ポインターをユーザーデータに格納し、使い慣れたread
、write
および同様のメソッドを実装するバインディングを提供します。 ___gc
_メタメソッドを実装することにより、io
ライブラリは、そのfile
オブジェクトの1つが、収集時に関連する_FILE *
_を閉じるようにします。
軽いユーザーデータは、Luaで何かへのポインターを値として表す方法です。値であるポインタを使用して lua_pushlightuserdata()
を呼び出すことで作成します。それらは、番号とほぼ同じ方法でLuaによって管理されます。これらは、Lua内で名前を渡すことができるようにCオブジェクトに名前を付ける必要があるが、オブジェクトの存続期間がLuaによって管理されていない場合に役立ちます。同じ値を持つ場合は数値が等しいのと同様に、同じポインターを保持している場合はライトユーザーデータは等しくなります。数値と同様に、スタック上にあるか変数に格納されている限り存在し、個別のメタテーブルがなく、ガベージコレクションも行われません。
さて、userdataはLua内から使用できるC側からのデータです。たとえば、io.inputとしてのファイルハンドルはuserdataです(print(type(io.input))を試してください)。 Lua C-APIをいじり始める場合(または、メタテーブルを設定できる空のユーザーデータを提供するnewproxy関数を使用する場合)、自分で必要になります(非表示の機能を参照 http:// lua-users.org/wiki/HiddenFeatures )(Lua-users wiki)。
良い紹介は次のとおりです: http://www.lua.org/pil/28.html
C関数については、Lua内から呼び出す関数としてC関数を登録するだけで済みますが、他のデータ型やC側のデータへのポインターなどは取得できません。
userdataを使用できます。必要なデータがいくらかある場合はいつでも、luagcによって管理されます。たとえば、C++オブジェクトに使用できます。 userdataを使用したc ++オブジェクトの例:userdataに保存すると、luaによって管理されるため、C++では忘れることができます。したがって、luavariablesでそれを参照し、c ++オブジェクトのmemberfunctionを呼び出す関数に渡すことができます。 (もちろん、汎用関数オブジェクトをユーザーデータに配置するなど、一般化する方法があります。これをアップバリューとしてCクロージャにバインドし、そのCクロージャをC++オブジェクトのlua側を表すluaobjectに登録します。ユーザーデータも)。 lua gcにオブジェクトを管理させたくなく、luaからc ++オブジェクトを参照したい場合は、そのオブジェクトへのポインターをライトユーザーデータとして保存できます。
まず、userdataは完全なuserdataを意味します。 CharArrayを実装するための2つのソリューションを次に示します。下記を参照してください:
//full userdata
extern "C" int newarray(lua_State* L)
{
int n = luaL_checkint(L, 1);
size_t nbytes = sizeof(CharArray) + (n - 1)*sizeof(char);
CharArray* a = (CharArray*)lua_newuserdata(L, nbytes);
a->size = n;
return 1;
}
//light userdata
extern "C" int newlarray(lua_State* L)
{
int n = luaL_checkint(L, 1);
size_t nbytes = sizeof(CharArray) + (n - 1)*sizeof(char);
CharArray* a = (CharArray*)(new char(nbytes));
lua_pushlightuserdata(L,a);
a->size = n;
return 1;
}
完全なユーザーデータは、事前定義された操作のない生のメモリ領域ですLuaから提供されます。したがって、ユーザーデータはガベージコレクターによって管理される必要があります。一方、light userdataは、Cポインターを表す値(つまり、void *値)にすぎません。ライトユーザーデータは、ガベージコレクターで管理する必要はありません(管理する必要はありません)。