Frage

  

Mögliche Duplizieren:
   eine C ++ Klassenmemberfunktion als C-Callback-Funktion

Ich schreibe eine objektorientierte Bibliothek eine C-Bibliothek (winpcap). Ich brauche die Callback-Funktion zu übergeben, die aufgerufen wird, wenn ein Netzwerkpaket als Funktion Zeiger kommt. Ich möchte ein Mitglied Funktionszeiger auf winpcap passieren, um mein Design objektorientierte zu halten und für verschiedene Objekte zu ermöglichen, verschiedene Pakete zu empfangen. Allerdings Mitgliederfunktionen soweit ich verstehen, eine andere Aufrufkonvention, und kann daher nicht auf eine C-Funktion übergeben werden. Gibt es eine Möglichkeit, dies zu beheben. Meine Experimente mit boost :: bind (was ich kaum andere verwalten zu benutzen als ein Versuch und Irrtum) nicht fruchtbar.

Gibt es eine Möglichkeit, die Aufrufkonvention eines Mitglieds Funktion zu ändern?

Dies ist die Definition der Callback-Funktion, die ich jetzt nutzen und die eigentlichen Vergehen den es winpcap

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

pcap_loop( adhandle, 0, pcapCallback, NULL );

Die pcap_loop nimmt nur den Namen der Funktion (die im Moment auf dem globalen Bereich ist). Dies ist die Definition des Funktionszeiger Parameter (3. Parameter von pcap_loop ). Da dieser Code von Drittanbietern ist, kann ich nicht wirklich das ändern. Ich hätte eine Memberfunktion haben, der diese Form annehmen kann:

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

Soweit ich es verstehe, wird die Memberfunktion Thiscall und die c Funktionszeiger verwendet werden will ein cdecl

War es hilfreich?

Lösung

Schauen Sie sich bitte detaillierte Thema über

Wie man einen Rückruf zu einer statischen C ++ Member-Funktion implementieren?

Wie man einen Rückruf zu implementieren, um eine nicht-statische C ++ Member-Funktion?

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

Andere Tipps

Sie können nur static Mitgliederfunktionen auf ein C-API übergeben.

Wenn Sie ein C-API-Aufruf eine Member-Funktion haben wollen, müssen Sie geben zwei Stücke von Daten: die (statisches Element) Funktion und das Objekt, für das es ist aufgerufen werden.

Normalerweise C API Rückrufe haben irgendeine Form von „Benutzerdaten“, die oft eine void*, durch die Sie Tunnel Ihr Objekt Adresse:

// 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);
}

Das pcapCallback sieht nicht aus, als ob es Benutzerdaten hat, obwohl, es sei denn, das ist, was param ist. Wenn das tatsächlich der Fall ist, werden Sie die Callback-Objekt Adresse in einigen globalen Variablen vor dem Aufruf der API speichern müssen. So etwas wie folgt aus:

// 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);
}

Wie immer mit globalen Daten, das ist gefährlich, wenn mehr als eine Instanz des Rückrufs am Leben ist. Ich habe versucht, den Schaden zu minimieren, so dass es funktioniert, wenn ihre Lebensdauer verschachtelt ist. Alles andere wird aber verletzt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top