2

私の図書館は、私の図書館のユーザーが情報を取得するために登録できるコールバック ポイントを提供します。コールバックの一般的な形式は、int型が int 値に依存するさまざまなパラメーターが続きます。そこで、以下のようにコールバックの型とそれを設定する関数を定義しました。

typedef void (* callback_func_t)(int type, ...);
void set_callback_func(callback_func_t callback);

私のライブラリ内で、私はこの関数をずっと呼び出しており、ユーザー セット関数、または私が提供しているデフォルトの関数です。できます。

ここで、いくつかの登録済みコールバックを呼び出せるように、間接的なレベルを追加したいと思います。問題は、まだ省略記号パラメーターを受け取る内部コールバック関数が、省略記号を使用してコールバック関数を呼び出さなければならないことです。結果として、私の内部関数は を解釈しtype、 からパラメータをアンパックして、パラメータva_listとして callbacj 関数に渡す必要があります。

void internal_callback(int type, ...) {
    va_list args;
    va_start(args, type);
    switch (type) {
    case 0: call_callback(type, va_arg(args, int)); break;
    // ...
    }
    va_end(args);
}

ただし、ユーザーのコールバックの実装では、va_listの値に応じて、同じ使用方法と引数の解釈も行われますtype。解決策は、コールバック関数への引数として を直接渡しva_list、内部コールバック関数の実装を明確にすることです。

typedef void (* callback_func_t)(int type, va_list args);

va_list私の質問は次のとおりです。引数として取るコールバック関数の型を定義するのは良い習慣ですか? 上記のようにコールバック関数の型を定義できますが、上の定義と比較して長所と短所は何ですか?

4

2 に答える 2

4

既知の有限数の型があると思いますか? もしそうなら、いくつかのレベルの型安全性のために列挙と共用体を使用しないのはなぜですか。これにより、偶然にも問題が解決します。

enum callback_arg_type { INT_ARG, DOUBLE_ARG, VECTOR_ARG };

union callback_arg
{
    int as_int;
    double as_double;
    struct { double x, y, z; } as_vector;
};

typedef void (*callback_func_t)(
    enum callback_arg_type type, union callback_arg arg);

引数のサイズの違いによっては、代わりにポインターを渡すことをお勧めします。コールバック呼び出しのためのより良い構文を提供するためにいくつかのマクロを提供することもできますが、それらがライブラリ内からのみ呼び出される場合は、価値がないかもしれません:

union callback_arg arg = { .as_int = 42 };
callback_fn(INT_ARG, arg);

自体はかなり短いです。

于 2010-10-27T14:00:24.063 に答える
3

私はva_listバージョンで行きます。ユーザーはすでに s を扱うことの恐ろしさに対処しているva_listので、ユーザーからそれを隠しても何も節約できません。

さらに、引数を再渡そうとするのではなくリストを使用すると、スタックの使用量が削減されます。関数に引数を再渡さなければならない場合、それらのすべての引数の新しいコピーが作成されますが、va_list型を渡すと、既にスタックにあるそれらの引数のインスタンスが使用されるだけです。

最後に、コードはよりシンプルになり (私が問題を正しく理解している場合)、各ユーザーがva_startandを呼び出す必要がなくなりますva_end(ほとんどの実装では、関数の出力コードはおそらくあまり変更されませんstdarg) 。それらはすべてこれらの呼び出しを入力する必要があり、(stdargプラットフォームでの s の実装方法に応じて) 戻る前に実際に呼び出すことを確認する必要がありますva_end(エラーの場合に早く戻ると見逃すのは簡単です)。

于 2010-10-27T14:18:44.233 に答える