2017-05-02 1 views
0

Ich fand mehrere ähnliche Fragen, aber die Lösungen passten nicht zu meinem Fall. In einer C++ - Methode rufe ich ein C api auf, das einen Callback als einen seiner Parameter akzeptiert.Nicht-statische Elementfunktion als Rückruf übergeben

class A 
{ 

    herr_t methodA(some parameters) {....} 

    void methodB(some parameters) 
    { 
     .... 

     int status = CAPI(other parameters, callback, last parameter); 
    } 

}; 

Der Prototyp ist CAPI

herr_t CAPI(some parameters, H5L_iterate_t op, other parameters); 

H5L_iterate_t definiert wird durch

herr_t (*H5L_iterate_t)(hid_t g_id, const char *name, 
         const H5L_info_t *info, void *op_data) 

methodA hat dieselbe Signatur wie H5L_iterate_t.
In methodeB,

status = CAPI(..., **(H5L_iterate_t)std::bind(&A::methodA, this, 
       std::placeholders::_1)**, ...); 

Der Kompilierungsfehler ich bekam, war "Kann von nicht konvertieren ... zu H5L_iterate_t". Ich frage mich, was ist der richtige Weg, um die nicht statische Member-Funktion als Rückruf zu übergeben.

Vielen Dank im Voraus.

+1

Mitglied Methoden Zeiger und Funktionszeiger sind nicht kompatibel. Sie könnten versuchen, eine freie Funktion, s static-Member-Methode oder s statusless Lambda zu schreiben, um einen Callback zu geben, der die tatsächliche Member-Methode aufruft und 'this' über' op_data' liefert. –

+0

Für C-Callbacks, glaube ich, dass Sie einen Funktionszeiger benötigen. Es kann also keine nicht statische Elementfunktion sein. –

+0

Ich weiß, eine statische Member-Funktion oder eine Plain-C-Funktion kann diesen Job erledigen. Aber ich brauche den Rückruf, um den Zustand des Objekts zu ändern. – Wqh

Antwort

2

C APIs einen Rückruf anbieten fast immer diesem Muster folgen:

extern "C" 
{ 
    typedef void(*callback_function)(void* data);  

    typedef int handle_type; 

    void do_something_with_callback(handle_type, callback_function, void *data); 
} 

Die Idee, dass sein, was Sie als data Argument übergeben, wenn do_something_with_callback aufgerufen wird, wird an die callback_function weitergegeben werden.

können Sie diese Benutzerdaten verwenden, um einen Zeiger auf Ihrem C++ Adresse des Objekts zu übergeben, die Sie dann wieder auf einen Zeiger auf Ihren Objekttyp umwandeln können:

struct my_object 
{ 
    void initiate() 
    { 
     // call the C interface, passing our c-style callback function with 
     // a pointer to this class as the user data 
     do_something_with_callback(handle_, &callback_launch_function, this); 
    } 

private: 
    static void callback_launch_function(void * data) { 
     // the data will always be a pointer to my_object - 
     // because that's what we passed. 
     auto self = reinterpret_cast<my_object*>(data); 
     self->handle_it(); 
    } 

    // this is our c++style callback 
    void handle_it() 
    { 

    } 

    handle_type handle_; 
}; 
+0

Ich habe das nicht versucht, aber ist es ein Problem, die nicht statische handle_it() von statischen Funktion zu nennen? – Wqh

+0

@Wqh vorausgesetzt, dass das 'data' Argument wirklich ein Zeiger auf ein' my_object' ist (und in diesem Fall haben wir sichergestellt, dass es ist) dann ist dies völlig legal und korrekt. –

+0

@Wqh: Nein, es ist kein Problem, weil der Code 'handle_it()' über einen Zeiger auf ein Objekt aufruft, so 'handle_it()' erhält einen 'this'-Zeiger wie erwartet. –

Verwandte Themen