- Luaのuserdataとlightuserdataとは何ですか?
- どこが必要ですか?
私はしばらくの間、私の頭を包み込みたいと思っていましたが、私が実際に理解しているチュートリアル/説明を見つけることはできません。Luaでuserdataとlightuserdataとは何ですか?
なぜそれらが必要なのですか。C関数をLuaメタデータに直接バインドするだけの理由はありませんか?
私はしばらくの間、私の頭を包み込みたいと思っていましたが、私が実際に理解しているチュートリアル/説明を見つけることはできません。Luaでuserdataとlightuserdataとは何ですか?
なぜそれらが必要なのですか。C関数をLuaメタデータに直接バインドするだけの理由はありませんか?
まあ、userdataは、Luaから使用できるC面のデータです。たとえば、io.inputのようなファイルハンドルは、userdataです(try(type(io.input)))。あなたがLua C-APIを使いこなし始めるならば、あなた自身が必要になります(またはnewproxy関数を使って空のuserdatumを与えます)。Lua-users wikiでメタテーブル(隠し機能http://lua-users.org/wiki/HiddenFeaturesを参照)を設定できます)。
良い導入がある:C関数のものについては http://www.lua.org/pil/28.html
:いや関数はLuaの中から呼び出されるようあなただけのC関数を登録することができますが、それはあなたの他のデータ型を取得することはありません、ポインタC側のデータなどへ
あなたはuser dataを使うことができます。必要なデータ量があれば、いつでもlua gcで管理することができます。たとえば、C++オブジェクトに使用できます。 C++のいくつかの例 - userdataを持つオブジェクト:userdataに保存することができます。そして、Luaによって管理されるようにC++でそれを忘れることができます。だからあなたはそれをluavariablesで参照し、それをC++オブジェクトのメンバー関数を呼び出す関数に渡すことができます。 (一般的な関数オブジェクトをuserdataに入れて、その値をC-クロージャにバインドし、そのC-クロージャをC++オブジェクトのlua-sideを表すluaオブジェクトに登録するようなことは一般化する方法があります。ユーザーデータも含まれます)。 lua gcにオブジェクトを管理させたくない場合に、単にluaのC++オブジェクトを参照したい場合は、軽いユーザーデータとしてポインタを格納することができます。
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内で名前を渡すことができるようにCオブジェクトに名前を付ける必要がある場合に便利ですが、オブジェクトの存続期間はLuaによって管理されません。同様の数値は同じ値を持つときは同じですが、軽いユーザーデータは同じポインタを保持しているときに等しいとみなされます。数字のように、スタック上にあるか変数に格納されていれば存在し、個々のメタテーブルを持たず、ガベージコレクションされません。
+1 – Eonil
まず、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のから提供していますノー事前に定義された操作と生のメモリ領域です。したがって、ユーザデータはガベージコレクタによって管理されなければなりません。 一方、軽いユーザーデータは、Cポインタ(つまり、void *値)を表す値に過ぎません。軽いユーザーデータは、ガベージコレクタによって管理される必要はありません(そうではありません)。
メタデータを* something *に付ける必要があります。ユーザーデータは合理的な選択です。メモリ管理についての詳細は – Textmode