0

Lua を使って何かをセットアップしようとしていますが、Lua の詳細は私の質問にとって重要ではありません。

私ができるようにしたいのは、関数を呼び出してOpenLib<T>(L)、特定のクラスのテーブル名 (およびそのテーブル) を取得し、Lua に登録することです。それは本質的にこれに要約されます:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

私はこれをいくつかの異なる方法で試しましたが、正しく動作させることができません。次のように myTable と myTableName を含む基本クラスを作成してみました。

class LuaInfo
{
public:
    static const char* myTableName;
    static luaL_reg* myTable;
}

次に、LuaInfo から継承して、必要な情報を入力します。LuaInfo から継承するすべてのクラスが同じ情報を取得するため、これはうまくいきませんでした。

template <class t>
class LuaInfo
// ...

class Widget : public LuaInfo を実行する必要があるため、初期化する構文が少しばかげていましたが、動作に近づいていました。

template <class T>
void OpenLib(lua_State* L)
{
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, LuaInfo<T>::myTableName, LuaInfo<T>::myTable, 0);
    }
}

これを正しくするためにいくつかのバリエーションを試しましたが、次のようなエラーが発生し続けます

undefined reference to `ag::LuaInfo<ag::ui::Widget>::myTable'

私がやりたいことは可能ですか?もしそうなら、それを行う正しい方法は何ですか?

4

2 に答える 2

1

使用する

template<typename T>
class LuaInfo
{
  static const char* myTableName;
  static lua_reg* myTable;
};

問題なく動作するはずです。

問題は、静的変数を定義する必要があることです。

このような行の束を含む単一のソースファイルはそれを解決します

luaL_reg* LuaInfo<ag::ui::Widget>::myTable = 0;
const char * LuaInfo<ag::ui::Widget>::myTableName = 0;

luaL_reg* LuaInfo<ag::ui::OtherClass>::myTable = 0;
const char * LuaInfo<ag::ui::OtherClass>::myTableName = 0;

等々。

これをより良くするためにマクロを定義したいかもしれません。

#define LUAINFOIMPL(X) luaL_reg* LuaInfo<X>::myTable=0; const char * LuaInfo<X>::myTableName=0
LUAINFOIMPL( ag::ui::Widget );
LUAINFOIMPL( ag::ui::OtherClass );

ただし、そのようにスケーリングするのは少し醜いです。私は特性スタイルテンプレートがこれを解決するかもしれないと考えていました..

于 2010-06-23T08:27:55.543 に答える
0

あなたの最初の試みは私にとってうまくいきます。静的メンバーを初期化するのを忘れて、それに関するリンク エラーが発生したと思います。これは私がしたことです:

template <class T>
static void OpenLib(lua_State* L)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (T::myTable && T::myTableName)
    {
        luaL_openlib(L, T::myTableName, T::myTable, 0);
    }
}

class LuaInfo
{
    public:
        static const char* myTableName;
        static luaL_reg* myTable;
};

//init static members
const char*  LuaInfo::myTableName = 0;
luaL_reg* LuaInfo::myTable = 0;

int main()
{
    OpenLib<LuaInfo>(0);
}

他の情報を提供したい場合は、次のOpenLibような新しいクラスを作成し、LuaInfoその新しいクラスをテンプレート パラメーターとして指定する必要があります。

しかし、なぜこの情報をテンプレート パラメーターとして使用する必要があるのでしょうか。IMO、これははるかに簡単です:

struct LuaInfo
{
    const char* myTableName;
    luaL_reg* myTable;
};

static void OpenLib(lua_State* L, LuaInfo info)
{
    // this func does some other stuff too that I'm omitting, important bit below
    if (info.myTable && info.myTableName)
    {
        luaL_openlib(L, info.myTableName, info.myTable, 0);
    }
}

int main()
{
    LuaInfo info = {/*some values here*/};
    OpenLib(0, info);
}
于 2010-06-23T07:47:17.037 に答える