6

重複の可能性:
C++クラスメンバー関数をCコールバック関数として使用する

Cライブラリ(winpcap)を使用してオブジェクト指向ライブラリを作成しています。ネットワークパケットが関数ポインタとして到着したときに呼び出されるコールバック関数を渡す必要があります。メンバー関数ポインターをwinpcapに渡し、デザインオブジェクトの方向を維持し、さまざまなオブジェクトがさまざまなパケットを受信できるようにします。ただし、私が理解している限り、メンバー関数の呼び出し規約は異なるため、C関数に渡すことはできません。これを修正する方法はありますか?boost :: bind(試行錯誤以外ではほとんど使用できません)を使った実験は実り多いものではありません。

メンバー関数の呼び出し規約を変更する方法はありますか?

これは、私が現在使用しているコールバック関数の定義であり、実際にwinpcapに渡すものです。

void pcapCallback( byte* param, const struct pcap_pkthdr* header, const byte* pkt_data );

pcap_loop( adhandle, 0, pcapCallback, NULL );

pcap_loopは、関数の名前を取ります(現時点ではグローバルスコープにあります)。これは、関数ポインタパラメータ(pcap_loopの3番目のパラメータ)の定義です。これはサードパーティのコードなので、実際に変更することはできません。この形式をとることができるメンバー関数が必要になります。

typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *);

私が理解している限り、メンバー関数はこの呼び出しを使用し、c関数ポインターはcdeclを必要とします

4

3 に答える 3

5

についての詳細なトピックを参照してください。

静的 C++ メンバー関数へのコールバックを実装する方法は?

非静的 C++ メンバー関数へのコールバックを実装する方法は?

http://www.newty.de/fpt/callback.html

于 2010-06-24T09:42:04.153 に答える
4

staticメンバー関数のみを C API に渡すことができます。

于 2010-06-24T09:24:07.560 に答える
4

C API でメンバー関数を呼び出したい場合は、2 つのデータを渡す必要があります: (静的メンバー) 関数と、それが呼び出されるオブジェクトです。

通常、C API コールバックには何らかの形式の「ユーザー データ」 (多くの場合 ) がありvoid*、オブジェクトのアドレスをトンネリングできます。

// Beware, brain-compiled code ahead!

typedef void (*callback)(int data, void* user_data);

void f(callback cb, void* user_data);

class cpp_callback {
public:
  virtual ~cpp_callback() {} // sometimes needed
  void cb(int data) = 0;
  callback* get_callback() const {return &cb_;}
private
  static void cb_(int data, void* user_data)
  {
    cpp_callback* that = reinterpret_cast<my_cpp_callback*>(user_Data);
    that->cb(data);
  }
};

class my_callback {
public:
  void cb(int data) 
  {
     // deal with data
  }
};

void g()
{
  my_callback cb;
  f(cb.get_callback(), &cb);
}

ただし、そうpcapCallbackでない限り、ユーザーデータがあるようには見えませんparam。その場合は、API を呼び出す前に、コールバック オブジェクトのアドレスを何らかのグローバル変数に格納する必要があります。このようなもの:

// Beware, brain-compiled code ahead!

typedef void (*callback)(int data);

void f(callback cb);

class cpp_callback {
public:
  cpp_callback() : the_old_cb_(this) {std::swap(the_cb_,the_old_cb_);}
  virtual ~cpp_callback()            {std::swap(the_cb_,the_old_cb_);}
  void cb(int data) = 0;
  callback* get_callback() const {return &cb_;}
private
  static cpp_callback* the_cb_;
  cpp_callback* the_old_cb_;
  static void cb_(int data, void* user_data) 
  {
    the_cb_->cb(data);
  }
};

class my_callback {
public:
  void cb(int data) { /* deal with data */ }
};

void g()
{
  my_callback cb;
  f(cb.get_callback(), &cb);
}

グローバル データの場合と同様に、コールバックの複数のインスタンスが有効な場合、これは危険です。ライフタイムがネストされている場合に機能するように、害を最小限に抑えようとしました。しかし、それ以外のものは傷つきます。

于 2010-06-24T09:38:59.370 に答える