[C++] Function Pointer bzw. Callback Problem

EdWood1

Grünschnabel
hi,

ich arbeite mit GTK+ und versuche gerade eine callback-funktion für meinen TCP-Socket zu verwenden. Allerdings bekomm ich ne Fehlermeldung beim Kompilieren. Habe jetzt mal den Teil mit dem Fehler hier reinkopiert:

Code:
bool TestApp::createConnection(int timeout_seconds, bool startup) {
...
      GIOChannel *socket_chan = g_io_channel_unix_new(m_socket.getRawSocket());    
      guint sourceID = g_io_add_watch(socket_chan, G_IO_IN, &TestApp::onDataAvailable, NULL);   // FEHLER
    
    return true;
}

gboolean TestApp::onDataAvailable(GIOChannel *gio, GIOCondition condition, gpointer data)
{
...
}

Die Funktion onDataAvailable wird also als Callback registriert und sollte aufgerufen werden sobald Daten am Socket anliegen. Nachdem ich mich allerdings mit Function Pointer nicht wirklich gut auskenn scheitere ich an folgender Meldung:

Fehler: »gboolean (TestApp::*)(GIOChannel*, GIOCondition, void*)« kann nicht nach »gboolean (*)(GIOChannel*, GIOCondition, void*)« für Argument »3« nach »guint g_io_add_watch(GIOChannel*, GIOCondition, gboolean (*)(GIOChannel*, GIOCondition, void*), void*)« umgewandelt werden
 
Ja ... nun gut, ich kenne mich mit den Bibliotheken, die du da verwendest, nicht aus. Aber das Problem ist relativ einfach und steht in der Fehlerbeschreibung deines Compilers schon drin. Es wird eine Freie, bzw. Globale Funktion benötigt. Oder eben eine statische, nicht aber eine nicht-statische Memberfunktion!

Nun hab ich aber mal nachgeguckt was deine g_io_add_watch-Funktion für Parameter hat. Zum glück hat sie einen User-data-Bereich!
Code:
class TestApp
{
    // ...
public:
    bool create_connection(const unsigned int, const bool);

private:
    inline static gboolean _on_data_available(GIOChannel* ptr_channel, GIOCondition condition, gpointer ptr_data)
    {    return static_cast<TestApp*>(ptr_data)->on_data_avaible(ptr_channel, condition); }

public:
    virtual gboolean on_data_available(GIOChannel*, GIOCondition const&);
    // ...
};

Code:
bool TestApp::create_connection(const unsigned int timeout_seconds, const bool startup) 
{
    // ...
    GIOChannel* ptr_socket_channel(g_io_channel_unix_new(m_socket.getRawSocket());    
    const guint sourceID(g_io_add_watch(socket_chan, G_IO_IN, &TestApp::_on_data_available, static_cast<gpointer>(this)));
    
    return true;
}

gboolean TestApp::on_data_available(GIOChannel* ptr_channel, GIOCondition const& condition)
{
    // ...
}
So sollte es doch gehen ;) Und es ist elegant umschifft! Das virtual kannst du weglassen ... je nachdem ob du es brauchst (polimophy) oder nicht. Die const-Ref ist einfach nur ein wenig Performance boost ... Und das const bei der create_connection-Funktion ein Schönheitsfehler den ich von dir behoben habe ;)

Viel Spaß damit ;)
 
Zurück