5

Lua に fetch() として登録されている Dfetch() という C 関数を作成しようとしています。Lua の関数として dog.beagle.fetch() を呼び出せるように階層化することを検討しています。コードの編成を改善するのに役立ちます。以下は私が持っているものですが、C関数を呼び出していません。サブテーブルではなくグローバルだけを実行すると、C 関数が呼び出されます。私はLuaを初めて使用するので、テーブルの設定が間違っているだけだと思います。

void myregister(lua_State *L, const char *libname, const char *sublibname, const luaL_Reg *l) 
{ 
    luaL_newmetatable(L, libname); 
    lua_newtable(L); luaL_setfuncs(L,l,0); 
    lua_pushvalue(L,-1); 
    if(sublibname != NULL) 
    { 
        lua_newtable(L); 
        lua_setfield(L, -2, sublibname); 
    } 
    lua_setglobal(L, libname);
}

luaL_Reg fidofuncModule[] = { {"fetch", Dfetch}, {NULL, NULL}};

main() では、次のように呼び出します。

lua_State * execContext = luaL_newstate();
//adding lua basic library
luaL_openlibs(execContext);

myregister(execContext, "dog", "beagle", fidofuncModule);


strcpy(buff, "dog.beagle.fetch();");
errorcode = luaL_loadbuffer(execContext, buff, strlen(buff), "line");
errorcode = lua_pcall(execContext, 0, 0, 0);

if (errorcode)
{
  printf("%s", lua_tostring(execContext, -1));
  lua_pop(execContext, 1);  /* pop error message from the stack */
}
//cleaning house
lua_close(execContext);

ありがとう、ティム

4

3 に答える 3

3

問題点)

では、この関数とスタックについて見ていきましょう。

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ためだけに使用すると、お互いのテーブルを踏みにじることになります。libnameluaL_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*/
于 2012-11-13T19:46:42.327 に答える
2
void myregister(lua_State *L, const char *libname, const char *sublibname, const luaL_Reg *lib) 
{ 
    // create 'libname' table
    lua_newtable(L); 

    // no sublib: just import our library functions directly into lib and we're done
    if (sublibname == NULL) 
    { 
        luaL_setfuncs(L, lib, 0); 
    } 
    // sublib: create a table for it, import functions to it, add to parent lib
    else
    {
        lua_newtable(L); 
        luaL_setfuncs(L, lib, 0); 
        lua_setfield(L, -2, sublibname); 
    }

    lua_setglobal(L, libname);
}
于 2012-11-13T19:48:44.753 に答える
0

fetchlibnameはではなく に登録されていsublibnameます。確認するには、電話の前に追加print(dog.fetch)してください。buff

これを試して:

void myregister(lua_State *L, const char *libname, const char *sublibname, const luaL_Reg *l) 
{ 
    lua_newtable(L);
    lua_pushvalue(L,-1); 
    lua_setglobal(L, libname);
    if(sublibname != NULL) 
    { 
        lua_newtable(L); 
        lua_pushvalue(L,-1); 
        lua_setfield(L, -3, sublibname); 
    } 
    luaL_setfuncs(L,l,0); 
}
于 2012-11-13T19:42:06.493 に答える