問題点)
では、この関数とスタックについて見ていきましょう。
luaL_newmetatable(L, libname);
OK、スタックにメタテーブル レジストリのテーブルが含まれるようになりました。
-1: table<libname>{possibly empty}
次:
lua_newtable(L);
スタックには以下が含まれるようになりました。
-1: table<new>{empty}
-2: table<libname>{possibly empty}
次:
luaL_setfuncs(L,l,0);
スタックを変更しません。ただし、一連の関数をテーブルに設定します。
-1: table<new>{bunch of functions}
-2: table<libname>{possibly empty}
次:
lua_pushvalue(L,-1);
これにより、スタックの一番上に値がコピーされます。これが一連の関数を含むテーブルです。
-1: table<new>{bunch of functions}
-2: table<new>{bunch of functions}
-3: table<libname>{possibly empty}
次:
if(sublibname != NULL)
{
lua_newtable(L);
これにより、空のスタックに新しいテーブルが作成されます。
-1: table<new2>
-2: table<new>{bunch of functions}
-3: table<new>{bunch of functions}
-4: table<libname>{possibly empty}
次:
lua_setfield(L, -2, sublibname);
ドキュメント に記載されているように、この関数は、指定されたテーブル キー名でテーブルに値を設定します。値はスタックの一番上の値ですが、それを入れるテーブルはindexです。
だからあなたはこれをしました:
-1: table<new>{bunch of functions, sublibname=table<new2>}
-2: table<new>{bunch of functions, sublibname=table<new2>}
-3: table<libname>{possibly empty}
それはあなたが望んでいたものではないと確信しています。続行するときに、それを修正する方法について説明します。
次:
}
lua_setglobal(L, libname);
これは、スタックの一番上を取り、それをグローバル テーブルに貼り付け、スタックの一番上からポップします。
したがって、スタックは次のようになります。
-1: table<new>{bunch of functions, sublibname=table<new2>{empty}}
-2: table<libname>{possibly empty}
そして、グローバルテーブルには次のものがあります。
_G[libname] = table<new>{bunch of functions, sublibname=table<new2>{empty}}
そのため、スタックのバランスを崩しただけでなく (ポップよりもプッシュが多かった)、実際に必要なものが得られませんでした。さらに、レジストリからのメタテーブルには...何も含まれていません。
ソリューション
それでは、これを修正しましょう。そしてちゃんとやりましょう。
あなたがやろうとしたことのほとんどすべてが間違っています。まず、サブテーブルを実行する唯一の理由は、次のようなコードが機能するようにするためです。
myregister(execContext, "dog", "beagle", fidofuncModule);
myregister(execContext, "dog", "dane", danefuncModule);
dog.beagle
このようにして、とを呼び出すことができますdog.dane
。そのためにmyregister
は、グローバル テーブルをチェックして、既にdog
テーブルがあるかどうかを確認する必要があります。存在する場合はそこにデータを保存する必要があり、存在しない場合は作成する必要があります。したがって、アルゴリズム全体が壊れています。
また、おそらく、dog.beagle
両方dog.dane
に独自のfetch
機能が必要です。レジストリにはテーブル用の場所が 1 つしかないため、呼び出しのdog
ためだけに使用すると、お互いのテーブルを踏みにじることになります。libname
luaL_newmetatable
これが私がそれを解決する方法です。これがあなたのやっていることでうまくいくかどうかはわかりませんが、これは私がすることです.
まず、すべてのnewmetatable
ナンセンスを忘れてください。私たちは常に新しいテーブルに基づいて作業します。したがって、内部テーブルを作成し、それに関数を設定します。
lua_newtable(L);
luaL_setfuncs(L,l,0);
したがって、スタックは次のようになります。
-1: table<new>{bunch of functions}
次のステップでは、サブライブラリ名がない場合は、これをグローバル変数の下に直接設定して、次をlibname
返す必要があります。
if(!sublibname)
{
lua_setglobal(L, libname);
return;
}
これにより、スタックから 1 つの値がポップされ、その場所に設定されます。
サブライブラリ名があるため、このテーブルをメイン テーブルに格納する必要があります。に既にテーブルがある場合_G[libname]
は、そのテーブルを取得します。それ以外の場合は、新しいテーブルを作成して に貼り付けます_G[libname]
。
lua_getglobal(L, libname);
if(lua_isnil(L, -1))
{
/*No table. Must create it and put it into the global*/
lua_newtable(L);
lua_pushvalue(L, -1); /*duplicate it on the stack*/
lua_setglobal(L, libname); /*pushes duplicate*/
}
この時点で、スタックには以下が含まれています。
-1: table<libname>{possibly empty}
-2: table<new>{bunch of functions}
sublibname
次に、フィールドとして使用して、作成したテーブルをそのテーブルに貼り付けます。
lua_pushvalue(L, -2); /*duplicates our created table*/
lua_setfield(L, -2, sublibname);
現在、スタックには以下が含まれています。
-1: table<libname>{stuff, sublibname=table<new>{bunch of functions}}
-2: table<new>{bunch of functions}
table は既にグローバル テーブルにあるため (そこから取得したか、作成時にそこに格納しました)、これで完了です。したがって、スタックをクリーンアップします。
lua_pop(L, 2); /*balance the stack. Remove our junk from it*/