5

私はこの中国のブログからこの質問を受け取ります http://chenyufei.info/blog/2011-02-28/wrap-c-function-closure-gcc-nested-function/ 著者は C 言語でクロージャを使用したいと考えています。 GCCにはネストされた関数(およびクロージャー)の機能があることがわかりました。例えば:

typedef int (*func_t)(int arg);


int foo(int a) {

    return a + 1;

}


func_t create_wrap_function(func_t f) {

    int wrapped(int arg) {

        // call original function

        int val = f(arg);

        fprintf(log_func_call, "arg: %d ret: %d", arg, val);

        return val;
    }

    return wrapped;
}

しかし、それは一般的な解決策ではありません。create_wrap_function は、 func_t が形式を制限するため、関数形式が固定されています。

ご存じのとおり、Lua にはクロージャがあり、C 関数も呼び出すことができます。私が実装したいのは、呼び出したい関数は foo1 と foo2 で、引数と戻り値の型が異なります。

int foo1(int a) {
    ...
    return intValue;
}

double foo2(char* str, double a) {
   ...
   return dblValue;
}

C クライアントでは、次のように関数を呼び出します。

lua_returnValue returnValue1 = Do_Lua_Wrap(__FILE__, __LINE__, foo1, 1);
lua_returnValue returnValue2 = Do_Lua_Wrap(__FILE__, __LINE__, foo2, "string data", 1.2345);

Do_Lua_Wrap では、foo1 と 1 を Lua 関数に渡し、通常のプロセスと同様に foo1 関数を呼び出します。次に、foo2 と 1 つの char* と 1 つの double 値を Lua 関数に渡し、通常のプロセスと同様に foo2 関数を呼び出します。Lua 関数では、 FILELINEに関する情報をログに 記録し、関数の引数に関する追加のログを書き込むことができます。

しかし、関数 Do_Lua_Wrap を C と Lua で記述する方法がわかりません。可能ですか?

もしよろしければ、アドバイスをいただけないでしょうか?

4

1 に答える 1

2

あなたは明らかに可変引数関数に興味がありますが、問題は Lua スタックにプッシュする引数の型を決定することです。いくつかのアプローチをお勧めします。

  1. 1 つ目は、 printf ファミリや高水準言語でよく使用されるバイナリ パッキング形式に似た形式文字列を含めることです。たとえば、 lpack Lua モジュールで使用されているフォーマット パターンを見てみましょう。重要なのは、フォーマット文字列をスキャンして、提供される引数の数と種類を判断することです。

  2. または、バリアント型を実装することもできます 。各引数は、そのような構造でラップする必要があります。また、引数の総数を最初のパラメータとして指定する必要があります。

  3. 最後に、可変個引数関数を使用する代わりに、2 つの配列で引数を渡すことができます。void *最初の配列には、2 番目の配列のポインターのターゲットに対応する列挙型が含まれます。この方法では、クライアント コードのハウスキーピングが最も多く必要になりますが、かなりクリーンです。配列の長さを指定する引数か、一方または両方の配列の最後にセンチネル値も必要です。

うまくいけば、これらの方法のいずれかがうまくいくはずです。個人的には、最初のオプションを選択し、lpackコードをガイドとして使用します。質問で指定された関数シグネチャにも最も近いものです。

于 2011-03-01T14:59:12.693 に答える