2010-12-01 29 views
22
  • Luaのuserdataとlightuserdataとは何ですか?
  • どこが必要ですか?

私はしばらくの間、私の頭を包み込みたいと思っていましたが、私が実際に理解しているチュートリアル/説明を見つけることはできません。Luaでuserdataとlightuserdataとは何ですか?

なぜそれらが必要なのですか。C関数をLuaメタデータに直接バインドするだけの理由はありませんか?

+1

メタデータを* something *に付ける必要があります。ユーザーデータは合理的な選択です。メモリ管理についての詳細は – Textmode

答えて

7

まあ、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側のデータなどへ

2

あなたはuser dataを使うことができます。必要なデータ量があれば、いつでもlua gcで管理することができます。たとえば、C++オブジェクトに使用できます。 C++のいくつかの例 - userdataを持つオブジェクト:userdataに保存することができます。そして、Luaによって管理されるようにC++でそれを忘れることができます。だからあなたはそれをluavariablesで参照し、それをC++オブジェクトのメンバー関数を呼び出す関数に渡すことができます。 (一般的な関数オブジェクトをuserdataに入れて、その値をC-クロージャにバインドし、そのC-クロージャをC++オブジェクトのlua-sideを表すluaオブジェクトに登録するようなことは一般化する方法があります。ユーザーデータも含まれます)。 lua gcにオブジェクトを管理させたくない場合に、単にluaのC++オブジェクトを参照したい場合は、軽いユーザーデータとしてポインタを格納することができます。

42

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によって管理されません。同様の数値は同じ値を持つときは同じですが、軽いユーザーデータは同じポインタを保持しているときに等しいとみなされます。数字のように、スタック上にあるか変数に格納されていれば存在し、個々のメタテーブルを持たず、ガベージコレクションされません。

+0

+1 – Eonil

1

まず、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 *値)を表す値に過ぎません。軽いユーザーデータは、ガベージコレクタによって管理される必要はありません(そうではありません)。

関連する問題