-3

オブジェクトとメンバーを指すベア関数ポインターがある場合、メンバー関数を呼び出す最良の方法は何ですか? thiscall基本的に、呼び出し規約で関数ポインターを呼び出したいと思います。

背景: 共有ライブラリ内のシンボルを動的に検索し、ファクトリ関数ポインターと呼び出したい特定のメンバー関数へのポインターを取得しています。メンバー関数自体は仮想ではありません。共有ライブラリを制御することはできません。バイナリを持っているだけです。

例:

typedef void * (*GenericFptr)();
GenericFptr lookup(const char *);

class CFoo;

GenericFptr factoryfn(lookup("CFoo factory function"));
CFoo *foo = reinterpret_cast<CFoo *>(factoryfn());

GenericFptr memberfn(lookup("CFoo member function"));

// now invoke memberfn on foo

現在union、関数ポインターをメンバー関数へのポインターに変換するために を使用しています。それは醜く、コンパイラの実装の詳細への依存関係を作成します。

class CFoo {
  public: 
  void *dummy() { return 0; }
};
typedef void * (CFoo::*FooMemberPtr)();

union {
  struct {
    // compiler-specific layout for pointer-to-member
    void *x, *y;
    GenericFptr ptr;
  } fnptr;
  FooMemberPtr memberfn;
} f;

f.memberfn = &CFoo::dummy; // init pointer-to-member
f.fnptr.ptr = memberfn;    // rewrite pointer

void *result = (foo->*f.memberfn)();
4

4 に答える 4

2

メンバー関数へのポインターは、より多くの情報が必要なため、関数へのポインターに格納できません (たとえば、多重継承の場合、呼び出しの前にこれにオフセットを適用する必要がある場合があります)。したがって、実装の詳細についての知識がなければできません。

移植可能にしたい場合、最も簡単なのはライブラリがメンバー呼び出しを行うラッパー関数を提供することです。

于 2010-06-30T13:11:09.037 に答える
1

残念ながら、メンバー関数ポインターには標準関数ポインターよりも多くの情報があり、標準関数ポインターを取得するときに、それをメンバー関数ポインターに変換すると、事実上、空中から余分なデータを生成しようとします。

あなたが試みていることを実行するための移植可能な方法はないと思いますが、組合が機能しているように見える場合は、おそらくそれを回避することができます。繰り返しになりますが、ボードの構築に使用するコンパイラごとに、これらのメソッドの表現と呼び出し規約を知っておく必要があります。

メンバー関数の名前を知っているなら、なぜあなたはfoo->dummy()例えばあなただけができないのですか?それ以外の場合、ルックアップ関数は完全なメンバー関数ポインターを提供する必要があるか、ライブラリーはこのポインターを渡すことができる通常の関数を備えたCラッパーインターフェイスを提供する必要があります。

于 2010-06-30T13:29:04.090 に答える
0

以下の回答によると、GCCで実行できますが、移植できません:

https://stackoverflow.com/a/5067992/705086

于 2014-03-21T09:11:34.783 に答える
0

次の 2 つのリンクは、洞察とおそらく解決策を提供します。this仮想メソッド、多重継承、仮想継承を考慮する必要があるため、引数を指定してメンバー関数ポインターを呼び出すことは通常は機能しないことに注意してください。

http://www.codeproject.com/KB/cpp/FastDelegate.aspx

http://www.codeproject.com/KB/cpp/ImpossiblyFastCppDelegate.aspx

于 2010-06-30T13:14:20.133 に答える