外部ライブラリが c++ 関数を呼び出すラッピング コードを作成しています (可変個引数テンプレートなどを使用)。重要な点は、外部ライブラリが c 関数を必要とすることです。これは合法であるため、通常は問題ありません。
LibraryFuncType fn = [](params) { ... }
これは手作業で簡単に行うことができますが、次のような方法でラッピングを自動化したいと考えています。
function_(context, "name", myfunc);
これを行うには、次のような関数が必要です。
template <ReturnType, ParamTypes...>
static void function_(Context &ctx, const std::string &name, std::function<ReturnType(ParamTypes...)> fn) {
ctx.registerFunction(name, [fn](State *state) -> int {
Context ctx(state);
return apply_helper<sizeof..(ParamTypes)>::apply(ctx, fn);
});
}
ここで、2 番目のパラメータ「ctx.registerFunction」は LibraryFuncType 型です。
しかし、これにはもちろん問題があります。なぜなら、'fn' のキャプチャにより、ラムダ変換がもはや合法ではないからです。ただし、「fn」をキャプチャしないと、ラムダでアクセスできなくなります。
これに対処する唯一の方法は静的変数を持つことだと思いますが、それを導入する最善の方法は私には明らかではありません。私が持っている現在の解決策は次のとおりです。
template <typename ReturnType, typename... ParamTypes>
struct function_helper {
static std::function<ReturnType(ParamTypes...)> fn;
function_helper(std::function<ReturnType(ParamTypes...)> _fn) {
fn = _fn;
}
static void registerFn(Context &ctx, const std::string &name) {
ctx.registerFn(name, [](state *state) -> int {
Context ctx(state);
return apply_helper<sizeof...<ParamTypes>>::apply(ctx, fn);
});
}
};
template <typename ReturnType, typename... ParamTypes>
std::function<ReturnType(ParamTypes...)> function_helper<ReturnType, ParamTypes...>::fn;
template <typename ReturnType, typename... ParamTypes>
void function_(Context &ctx, const std::string &name, std::function<ReturnType(ParamTypes...)> fn) {
function_helper<ReturnType, ParamTypes...> reg(fn);
reg.registerFn(ctx, name);
}
技術的にはこれは機能しますが、明らかに危険です (そしてハッキーです)。同じシグネチャを持つ 2 つの関数で「function_helper」を使用すると、そのうちの 1 つに「fn」が正しく設定されないためです。
さらに、「function_」で静的変数を宣言するだけで、同じ危険な静的変数を実行できます。問題を回避する正しい方法についての洞察につながることを期待して、クラスを作成しました。
キャプチャを必要としないラムダを使用するより良い方法 (または、キャプチャを行うラムダを c 関数に変換する方法) を知っている人はいますか?