1

テンプレート パラメーターを使用して静的ラッパー関数を作成する際に問題が発生しています。int (lua_State *)次の関数に渡すことができるように特定の署名が必要なため、関数をラッパー関数に直接渡したくありません。

lua_pushcfunction(L, function);

(そうです、自動生成された lua ラッパーを使用します。)

私が最初に考えたのは、非型テンプレート引数として関数ポインターを使用してテンプレート関数を作成することです。

template <void(* f)(void)>
int luaCaller(lua_State * _luaState)
{
    f();

    return 0;
}

これまでのところ、これはかなり良さそうです。この関数には適切なシグネチャがあり、テンプレート引数を介して渡した関数を呼び出します。

&(luaCaller<myFunc>)

これを別の関数でラップしようとすると、私の問題が発生します。型のないテンプレート パラメーターは外部にリンクする必要があるため、次の処理は失敗します。

void pushFunction(lua_State * _luaState, void(* _f)(void))
{
    lua_pushcfunction(_luaState, &(luaCaller<_f>));
}

関数のアドレスはコンパイル時に知る必要があるため、これは理にかなっています。任意のポインターをスローして、コンパイラーがどのクラスを作成するかを知ることを期待することはできません。残念ながら、コンパイル時に既知の関数ポインターを追加しても失敗します。関数ポインターの値は _a にコピーされているため、_a はコンパイル時にまだ技術的に認識されていません。このため、次のことが機能することを期待しています。

void pushFunction(lua_State * _luaState, void(* const _f)(void))
{
    lua_pushcfunction(_luaState, &(luaCaller<_f>));
}

または多分

void pushFunction(lua_State * _luaState, void(* & _f)(void))
{
    lua_pushcfunction(_luaState, &(luaCaller<_f>));
}

最初のケースでは、値の変更が許可されていないため、外部リンクされている場合でも、技術的には外部リンクのままであることがわかっています。2 番目のケースでは、参照として渡されています。これは、同じリンケージを持つ必要があることを意味します。しかし、これらの試みはどちらもうまくいきません。なんで?何とかこれを回避することは可能ですか?別の関数を呼び出す関数をきれいに自動生成するにはどうすればよいですか?

4

2 に答える 2

1

修飾子は、const何かを変更することを許可されていないことを意味しますが、それがコンパイル時の定数であることを意味するわけではありません。の初期値は_a、関数が呼び出されたときに実行時に決定されます。* const &aの場合、参照の基礎となるオブジェクトが ではない場合、値は別のスレッドなどの外部手段によって実行時に変更されることさえありますconst

完全にテンプレート化されたラッパーを機能させるには、考えられるテンプレート引数ごとに関数をコンパイルするのに十分な情報をコンパイラに提供し、それらの関数を切り替えるロジックを提供する必要があります。テンプレート システムは関連する関数を生成して整理しますが、動的なディスパッチャーではありません。

オブジェクトに関数ポインタを追加しlua_Stateてテンプレート パラメータを削除できれば、それが 1 つの解決策になります。

関数ポインターを へのテンプレート引数にすると、ソリューションは機能しますdoCallerが、それはその目的を無効にします。

于 2013-05-18T01:47:42.030 に答える
1

ラッパー関数内で呼び出したい二次関数をバインドするために非型関数テンプレート アプローチを使用するのではなくstruct、静的luaCallerメソッドで a を使用できます。luaCallerこれにより、 に渡すために必要な関数シグネチャを維持できるはずですlua_pushcfunction

たとえば、次のような構造体を作成できます。

template<void (*f) void>
struct wrapper
{   
    static int luaCaller(lua_State * _luaState)
    {
        f();

        return 0;
    }
};

template<typename Functor>
void doCaller(lua_State * _luaState, Functor wrapper)
{
    Functor::luaCaller(_luaState);
}

次に、次のように呼び出します。

doCaller(&luaState, wrapper<my_func>());
于 2013-05-18T02:08:40.193 に答える