2017-05-12 15 views
0

CラッパーをC++で作成しようとしています。C++クラスメンバ関数からC構造体ポインタへ

しかし、クラス内の関数を構造体関数ポインタに変換することはできません。

myCallback関数は、オーバーライドする必要があるため、静的に使用しないでください。ここで

はサンプルコードです:ここでは

#include <iostream> 

extern "C" { 
typedef struct _client_config 
{ 
    void (*on_connect)(void *client, int result); 
} client_config; 
} 

class Parent 
{ 
public: 
    Parent() {}; 
    ~Parent() {}; 

    virtual void myCallback(void* hello, int world) = 0; 
}; 

class Child : public Parent 
{ 
public: 
    Child() {}; 
    ~Child() {}; 

    void myCallback(void* hello, int world) 
    { 
     printf("Hello World! \n"); 
    } 
}; 

int main(void) 
{ 
    Parent* myClass = new Child(); 

    client_config* myClientConfig = (client_config *)malloc(sizeof(client_config)); 

    myClientConfig->on_connect = myClass->myCallback; 

    return 0; 
} 

は、コンパイラはコンパイル時にこう言われる、

Error 1 error C3867: 'Parent::myCallback': function call missing argument list; use '&Parent::myCallback' to create a pointer to member 
Error 2 error C2440: '=' : cannot convert from 'void (__thiscall Parent::*)(void *,int)' to 'void (__cdecl *)(void *,int)' 

誰もが構造体の関数ポインタにクラスのメンバ関数をバインドする方法を指摘することができますか私はここで間違っていますか?

答えて

0

Cライブラリの関数ポインタは、フリー関数extern "C"とのみ互換性があります。 (静的メンバー関数でも互換性はなく、言語リンケージは間違っています)。

あなたはトランポリンのような機能を使用する必要があります。あなたのオブジェクトがどこにあるのかをポインタで確認してください(ライブラリーはユーザーデータの何らかの形を保存する手段を提供しますコールバック内で取得されたのでしょうか?おそらくclientパラメータはこのようなものです。ドキュメントを読む必要があります)、Parent*にキャストして、メンバーコールを実行します。コンパイラはこれをあなたのためにしません。

extern "C" void connect_trampoline(void* client, int result) 
{ 
    Parent* my_object = static_cast<Parent*>(client); 
    my_object->myCallback(result); 
} 

myClientConfig->on_connect = &connect_trampoline; 

C++ライブラリは、通常、独自の状態を運ぶことができるstd::functionを受け入れることにより、例えば、これを容易にするためにコード化されています。しかし、Cライブラリが使用するCプログラミングスタイルでは、メンバーを使用する前にオブジェクトを見つけて醜いキャストをしなければなりません。

ライブラリはコールバックへのあなたのコントロール下でポインタのいくつかのフォームにアクセスできるようにしませんが、コールバックに関連付けられているライブラリオブジェクトへのポインタを渡すん、あなたがオブジェクトをルックアップするためにグローバルstd::map<library_object*, Parent*>を使用することができた場合。このアプローチはまた、キャストを回避する。


はあなたのために保持するためにライブラリにあなたのオブジェクトへのポインタを渡したとき、あなたはそれをあなたが後で戻ってキャストしますまったく同じタイプ(この場合は Parent*)を得ていることに注意してください。 Derived*を指定した場合、効果は非常に悪い reinterpret_cast<Parent*>(p_derived)のことです。 ( static_cast Parent*にライブラリへのポインタ、 static_castを与えるとき void*にあなたはそれを取り戻す、とC++標準では、このシーケンスは reinterpret_castと全く同じ動作であると言うとき)

関連する問題