Luaのコロン演算子 ( :
) は、関数に対してのみ使用されます。次の例を検討してください。
meta = {}
meta["__index"] = function(n,m) print(n) print(m) return m end
object = {}
setmetatable(object,meta)
print(object.foo)
index 関数は、渡された 2 つの引数を単純に出力し、2 番目の引数を返します (単に実行object.foo
すると構文エラーになるため、2 番目の引数も出力します)。出力はtable: 0x153e6d0 foo foo
新しい行になります。変数__index
とその名前を検索しているオブジェクトを取得します。で置き換えるobject.foo
と、次のobject:foo
ようになります。
input:5: function arguments expected near ')'
これは:
inobject:foo
が のシンタックス シュガーでobject.foo(object)
あるためです。そのため、Lua は関数呼び出しに引数を提供することを期待しています。引数 ( object:foo("bar")
) を指定した場合、次のようになります。
table: 0x222b3b0
foo
input:5: attempt to call method 'foo' (a string value)
したがって、__index
関数は引き続き呼び出されますが、引数は渡されません。Lua は単に戻り値を呼び出そうとします。:
したがって、メンバーには使用しないでください。
それはさておき、Lua と C の間で変数を同期する方法を見てみましょう。これは実際にはかなり複雑で、さまざまな方法があります。__index
1 つの解決策は、とを組み合わせて使用することです__newindex
。C で構造体を作成している場合は、beagle
これらの C 関数を作成し、C 構造体へのポインターを上位値として持つ C クロージャーとして Lua テーブルのメタテーブルにプッシュすることをお勧めします。Lua の一般的なクロージャーに関する情報については、これを参照してください。lua_pushcclosure
参照できる単一の構造体がない場合はvariableName-variableLocation
、C 側で何らかの形でペアを格納し、それぞれがどのような型であるかを知る必要があるため、さらに複雑になります。実際の Lua テーブルでそのようなリストを維持できるのでdog.beagle
、変数名から 1 つまたは 2 つの何かへのマップになります。この「何か」にはいくつかのオプションがあります。まず、1 つのライト ユーザー データ (つまり、C ポインター) ですが、それが何を指しているのかを理解するという問題が発生します__index
。__newindex
. もう 1 つのオプションは、2 つの関数/クロージャーをプッシュすることです。処理する必要がある型 (数値、文字列、テーブルなど) ごとに C 関数を作成し、変数ごとに適切な関数をプッシュするか、指定されている型をパラメーターとして受け取る uber-closure を作成することができます。プッシュするアップ値を変えるだけです。この場合、関数__index
と__newindex
関数は、指定された変数名に対応する適切な関数を検索して呼び出すだけなので、おそらく Lua で実装するのが最も簡単でしょう。
2 つの関数の場合、次のdog.beagle
ようになります (実際の Lua 構文ではありません)。
dog.beagle = {
__metatable = {
__index = function(table,key)
local getFunc = rawget(table,key).get
return getFunc(table,key)
end
__newindex = function(table,key,value)
local setFunc = rawget(table,key).set
setFunc(table,key,value)
end
}
"color" = {
"set" = *C function for setting color or closure with an upvalue to tell it's given a color*,
"get" = *C function for getting color or closure with an upvalue to tell it to return a color*
}
}
上記に関する注意事項: 1. オブジェクトの__metatable
フィールドを直接設定しないでください。実際のメタテーブルを非表示にするために使用されます。setmetatable(オブジェクト、メタテーブル) を使用します。2. の使用法に注意してくださいrawget
。そうしないと、オブジェクトのフィールドを内部から取得しようとすると__index
無限再帰になるため、これが必要です。rawget(table,key)
3. イベント return で、または戻り値に/メンバーnil
がない場合は、もう少しエラー チェックを行う必要があります。get
set