0

関数ポインターに問題があり、ネット上でこの問題を解決するのに役立つものは何も見つかりませんでした。

void 関数のポインターを取る C API の関数があります。

extern int APIFunction(int, void (*func)(int));

API関数を呼び出すときに入れたい関数を持つクラスがあります。

class MyClass
{
   public:
      void myFunction(int status, otherAPi arguments...);
};

次に、メンバー関数へのポインターを作成し、クラスの新しいインスタンスを作成しました

typedef  void (MyClass::*MyClassFunctionPointer)(int stat, otherAPi arguments...);
MyClassFunctionPointer fctPointer= &MyClass::myFunction; 
LicenseSecurity instance;  

作成した関数ポインターを使用して APi 関数を呼び出そうとすると、エラーが発生します。

int stat = APIFunction(5, fctPointer ); // -> error 1
int stat = APIFunction(5, instance.*fctPointer ); // -> error 2

最初と2番目のケースでそれぞれエラーが発生しました:

E2034 Impossible to convert 'void (MyClass::*)(int, otherAPITypes...)' into 'void (*) (int, otherAPITypes...)'
E2342 Bad type correspondence in the parameter 'func' ('void (*)(int, otherAPITypes...)' desired, 'void(int, otherAPITypes...)' obtained)

API 関数にアクセスできないため、変更できません。問題を要約するには:どのように「単純な」C関数ポインタを取得して、クラスのメンバー関数から関数の引数に入れるには?

ありがとう

4

4 に答える 4

2

残念ながら、できません。ごめん。

std::function理想的には、API は、フリー関数またはメンバー関数をラップできるようなものを受け入れます。しかし、API を変更できない場合は、無料の機能を提供するしかありません。

于 2013-04-11T20:48:13.783 に答える
0

そのような古い C API では、残念ながらこれを行う方法がありません。

あなたがしなければならないことは、静的関数または非メンバー関数を作成してコールバックを取得し、オブジェクトのどのインスタンスでメンバーを呼び出すかを判断することです。一部の C API では、ユーザー データをコールバックに渡すことができます。その場合、それを使用して問題のthisポインターを格納します。それができない場合は、グローバル オブジェクトまたはシングルトン オブジェクトを使用して、そのようなコールバックを 1 つしか登録できないようにすることができます。

于 2013-04-11T20:58:08.887 に答える
0

コールバックは、スタンドアロン関数またはクラスの静的メソッドとして宣言できます。注意が必要な部分は、コールバック内のクラス インスタンス ポインターにアクセスすることです。

理想的には、適切に設計された API により、ユーザー定義の値をコールバックに指定できます。これにより、クラス インスタンスを簡単に渡して、コールバック内で直接アクセスできます。しかし、そのような API を使用していないように思われるため、回避策を使用する必要があります。

一度に API で使用されるクラス インスタンスが 1 つだけの場合は、インスタンス ポインターをグローバル変数に格納し、コールバックでグローバル変数を使用してインスタンスにアクセスすることができます。

しかし、複数のクラス インスタンスを同時に使用している場合は、VCL のMakeObjectInstance()関数に似た、TWndMethod署名付きクラス メソッドを Win32 ウィンドウ プロシージャ コールバックとして使用できるようにするサンク ソリューションを探しています。基本的に、実行可能メモリのブロックが動的に割り当てられ、スタブ アセンブラー コードがブロックに書き込まれ、インスタンス ポインターとクラス メソッド ポインターもブロックに格納されます。ブロックは、関数ポインタであるかのように API に渡されます。API が「関数」を呼び出すと、スタブ コードが実行されます。これは、コール スタックと CPU レジスタを操作して、格納されたインスタンス ポインタを非表示として渡す格納されたクラス メソッド ポインタを呼び出す必要があります。this他のパラメーター、コール スタック、関数の結果などのセマンティクスを保持しながら、パラメーターを変更します。

C++ では、この種のサンクをネイティブに実現するものはありません。手動で実装するのは難しくありませんが、簡単でもありません ( MakeObjectInstance()VCL の Classes.pas ソース ファイルのソース コードを参照してください)。最も難しい部分は、特定のクラス メソッドのシグネチャのセマンティクスに一致する必要なスタブ コードを考え出すことです。

于 2013-04-13T05:17:35.600 に答える