Callback aus C-dll

Alles rund um die Programmierung mit Qt
Antworten
delegug
Beiträge: 11
Registriert: 29. Juni 2010 13:43

Callback aus C-dll

Beitrag von delegug »

Tag,

ich habe eine dll, die in C-geschrieben ist. die dll hat eine Funktion mit Callback, in der man einen Funktionszeiger übergibt.
Leider kann ich jetzt nur eine globale Funktion aufrufen lassen, da meine c-dll keine Klassen objekte kennt.
Ich möchte aber, dass meine Klasse ein Signal auslöst, sobald die Callback-Funktion ausgelöst wird. Wie bekomme ich eine Verbindung zwischen der globalen Funktion und das Signal in der Klasse?



Code: Alles auswählen

bool opcControl::registerCallback()
{
    bool result=false;
    typedef bool (*RegType)(void (*)(int,char *));
    RegType RegCallBack= (RegType) lib.resolve("registerCallback");
    if (RegCallBack) {
        //Callback->funktion registrieren
        result=RegCallBack(&datachange);
        ...




}

Code: Alles auswählen

void datachange(int handle,char* value)
{
    qDebug()<<handle<<value;
    QString newValue=value;
  
    ///????????????????????????????????
    
}
[/url]
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das ist leider eine doofe Library. Denn normalerweise kommt bei einem C-Callback auch ein Parameter "void* UserData" mit. Demm könntest du deinen this-Zeiger mitgeben.
Aber so wie du das gepostet hast, geht es nicht.

Was für eine dll ist das denn? Kannst du die nicht wechseln? Oder dem Developer sagen, er soll doch bitte Konventionen einhalten, und einen UserData-Pointer mitnehmen?
delegug
Beiträge: 11
Registriert: 29. Juni 2010 13:43

Beitrag von delegug »

ich habe jetzt den code der dll mir besorgt und soweit verstanden. wie kann ich nun diesen void* UserData einfügen und das this-Object übergeben? Gibt es ein Beispiel?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

delegug hat geschrieben:ich habe jetzt den code der dll mir besorgt und soweit verstanden. wie kann ich nun diesen void* UserData einfügen und das this-Object übergeben? Gibt es ein Beispiel?
Was willst du denn jetzt machen? Die Lib anpassen? Oder gibt es doch einen Callback mit void* userdata?

Hier einfach ein kurzes Beispiel:

Code: Alles auswählen

#include <iostream>

typedef void (*CallBack)(int, void*);

// Das ist die Funktion, wie sie von der Library zur Verfügung gestellt wird.
void c_function_with_callback( int value, CallBack cb, void* user_data)
{
    value *= 2;
    cb(value, user_data);
}

struct Type {
    // Das soll jetzt im Callback aufgerufen werden
    void doIt(int value) {
        std::cout << "Member Function Callback " << value << std::endl;
    }
};

// Unsere Callback-Funktion, die an die Lib-Funktion übergeben wird.
void my_callback_fun(int value, void* data) {
    Type* obj = static_cast<Type*>(obj);
    obj->doIt(value);
}

int main() {
    Type t;
    c_function_with_callback(10, my_callback_fun, &t);
}
Für mehr Beispiele sollte google (z.B. nach "c++ c-callback user data") befragt werden.
delegug
Beiträge: 11
Registriert: 29. Juni 2010 13:43

Beitrag von delegug »

ok, vielen dank. hab die lib angepasst und funktioniert mit übergabe des klassenobjekts und danach diesen casten.
hier noch ein hilfreicher link
http://www.newty.de/fpt/callback.html
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Zwei kurze Anmerkungen zu der Seite (scheint veraltet zu sein, jedenfalls aus C++-Sicht):
1) #include <iostream.h> gibt es nicht (mehr)! Das heißt jetzt nur "<iostream>
2) Casts im C-Style (wie auf der Seite) sollte man in C++ nicht machen, sie veschleiern was eigentlich wirklich passiert. C-Casts können sein
* static_cast
* reinterpret_cast
* const_cast
Bitte verwende immer die C++-Casts (auch wenn es etwas mehr Schreibaufwand ist), dann weißt du auch ganz genau, was da wirklich passiert, und bei einem cast-Fehler beschwert sich der Compiler!
Hier in dem Beispiel ist ein static_cast alles was du brauchst.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Wie bekomme ich eine Verbindung zwischen der globalen Funktion und das Signal in der Klasse?
Prinzipiell geht das aber auch.
gibt nur ein unschoenes Gebilde aus einer globalen Instanz einer klasse die statische Methoden auf Signale mappt. Oder man schreibt ne Proxy Dll, die das Interface anpasst und die "Clients" sauber verwaltet.

Die Loesung mit dem "Userdata" ist aber definitiv die elegantere und flexiblerer. Leider gibts noch paar Bib-Erzeuger, die das ned unterstuetzen. Dafuer muss man dann ganz schoen unsaubere oder umstaendliche Dinge in Kauf nehmen.

Ciao ...
Antworten