Anzeige:
Ergebnis 1 bis 4 von 4

Thema: [C++] C API Callbacks

  1. #1
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477

    Post [C++] C API Callbacks

    Wenn man aus C++ Code heraus C APIs benutzt, kommt man manchmal in die Situation eine Callback Funktion im C Stil angeben zu müssen, aber man gerne eine Methode einer bestimmten Instanz einer eigenen Klasse aufgerufen hätte.

    Das läßt sich üblicherweise ohne weitere Probleme bewerkstelligen, denn die Funktionen der C API, die zum Registrieren der Callbacks benutzt werden, bzw. die Signaturen der Callbacks sehen üblicherweise ein Kontextargument vor.

    Dieses Kontextargument benutzt man um die Instanz der Klasse zu transportieren, sie ist ja in diesem Fall unser Anhaltspunkt.

    Konkret sieht das so aus:
    Code:
    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    ///////////////////// C API /////////////////////
    // Ab hier steht die "Simulation" unserer C API, d.h. dieser Abschnitt dient nur zur
    // Vereinfachung des Beispiels, normalerweise wäre das in der jeweiligen Bibliothek
    // implementiert und wir würden den entsprechenden Header inkludieren
    int numArgs;
    char** args;
    
    // die simulierte Callbackregistrierfunktion ruft nur gleich direkt den Callback
    // auf
    int registerCallback(int callback(void*, int, char**), void* context)
    {
        if (callback == 0) return 0;
    
        return callback(context, numArgs, args);
    }
    ///////////////////// C API /////////////////////
    
    // Ab hier beginnt der eigentliche C++ Teil
    
    class CallbackHandler
    {
    public:
        // Die static Methode entspricht in ihrer Signatur genau den Anforderungen
        // für den C API Callback. Da sie static ist, kann sie ohne Instanz benutzt werden
        // und kann darum an die C API weiter gegeben werden, die ja nichts von
        // Instanzen weiß
    
        static int callback(void* context, int argCount, char** args)
        {
            cout << "CallbackHandler::callback: context=" << context << endl;
            
            if (context == 0) return 0;
            
            // wie wir "wissen" ist das Kontextargument unsere Instanz, also brauchen wir
            // nur zu casten und die "echte" Methode zur Behandlung der Daten aufrufen
            CallbackHandler* handler = reinterpret_cast<CallbackHandler*>(context);
    
            return handler->doCallback(argCount, args);
        }
    
    private:
        // Methode die die Daten eigentlich verarbeiten soll und dabei Zugriff auf
        // eine bestimmte Instanz der Klasse haben soll, also nicht static sein kann
        int doCallback(int argCount, char** args)
        {
            cout << "CallbackHandler::doCallback: this=" << this << endl;
            
            for (int i = 0; i < argCount; ++i)
            {
                cout << "args[" << i << "]=" << args[i] << endl;
            }
    
            return 1;
        }
    };
    
    int main(int argc, char** argv)
    {
        // Daten für unsere C API Simulation bereitstellen
        numArgs = argc;
        args    = argv;
    
        // Unseren Handler erzeugen
        CallbackHandler handler;
    
        // static Methode als Callback angeben und die Instanz, bzw. den Pointer darauf
        // als Wert für das Kontextargument
        bool success = registerCallback(CallbackHandler::callback, &handler) != 0;
    
        cout << "success=" << (success ? "true" : "false") << endl;
        
        return 0;
    }
    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  2. #2
    Registrierter Benutzer
    Registriert seit
    19.02.2004
    Beiträge
    10

    Thumbs up

    Danke für die Hinweise. Ich werde morgen ausprobieren.
    Raspen

  3. #3
    Registrierter Benutzer
    Registriert seit
    28.07.2000
    Beiträge
    123
    bei callbacks kann man sich gelegentlich auch mit strukturen behelfen, wenn die anzahl der zulässigen parameter nicht ausreicht.

    ich habe das mal bei fltk 1.1.7 gemacht, da ich mir die verwendung von globalen variablen untersagt hatte ;-). war ganz witzig, hat aber ganz schön zeit gekostet ...

    gruesse

    reinhard

    ps: alternativ natürlich eine klasse ;-) wenn man schon gezielt bei der objektorientierten SWE bleiben will ...

  4. #4
    Angelina_Apr
    Gast

    C C API Callbacks

    Hi All,

    I also need to have this connector for webservices API. i think it would be really useful connector for many organizations.

    Please let me know what is the status or when it can be released ?

    Thanks,
    Piyush.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •