7

C++ ライブラリを C でラップする必要があります。この C++ ライブラリは、コールバック関数を定義します。例えば:

    // from C++ library

    typedef X CallbackFn(Y y); // X and Y are classes

    class Z
    {
    public:
            void addCallback( CallbackFn* fn ) { callbackFn = fn; }
    private:
            CallbackFn* callbackFn;
    };

C ラッパーでは、C++ コールバックを呼び出す新しい C コールバックを定義できます。このようなもの:

    // in C wrapper

    extern "C" {

    typedef int CallbackFnC(int n, ... );

    CallbackFnC *callbackFnC;

    int addCallback(void* handle, CallbackFnC* fn) // handle is pointer to Z instance
    {
        callbackFnC = fn;
        ((Z*)handle)->addCallback(callbackFnCPP);
    }

    }

    X callbackFnCPP(Y y)
    {
        int rtn = callbackFnC(y.n, ...);
        return X(rtn);
    }

ここで、Y の関連メンバーを C コールバック関数の引数にマップでき、C の戻り値から戻り値の型 X を十分に構築できると仮定します。

これはうまくいきますか?新しい C コールバックを定義する方法はありませんか?

新しい C コールバックは の内側にある必要がextern "C"あり、C++ コールバックの定義済みインスタンスは外側にある必要がありますか?

4

1 に答える 1

2

はい、C++ コールバックを C コールバックと C++ ラッパー関数に置き換えることは (いくつかの注意事項がありますが) 動作しますが、C++ コールバックが (C でもサポートされるプリミティブ型とは対照的に) クラスまたは参照を渡す/返すことを主張する場合は動作しません。ラッパー メソッドが唯一の可能な解決策です。

ラッパー関数を使用する際の主な注意点は、ラッパー関数には、呼び出す正しい C 関数を見つける何らかの方法が必要であるということです。グローバルを使用するのは簡単な解決策ですが、今ではプログラム全体に対して 1 つのコールバックに制限されています (Z オブジェクトの数に関係なく)。より柔軟なソリューションは、C++ コールバックの設計に依存し、簡単なもの (登録時に、コールバックに提供される任意のユーザー データを提供できます) から非常に難しいものまでさまざまです。

于 2012-12-18T14:28:54.983 に答える