Einer C Funktion eine C++ Member-Funktion zum Callback übergeben.

arothe

Grünschnabel
Liebes Team,

ich versuche mich seit Tagen daran einer Funktion aus einer C-Bibliothek eine C++ Funktionsreferenz zu übergeben.

Bei der Bibliothek handelt es sich um den Jack-Audio Server. Der Server verbindet einen oder mehrere angemeldete Clients mit der Soundkarte und realisert so die Audio-Ausgabe. Ich selbst möchte für diesen Server einen Client schreiben, also ein Programm, dass Audio ausgibt.

Um die Verbindung zum Server herzustellen, muss man dem Server eine Referenz auf eine Funktion übergeben, die dieser aufruft, wenn mein Programm seine Audio-Daten ausgeben darf. Mein Programm ist also in C++ geschrieben, folglich ist die Funktion, die Callback Funktion werden soll, eine Member Funktion. Normale C Funktionen werden von dem Server akzeptiert. Meine C++ Member Funktion jedoch nicht. Es gibt die folgende Fehlermeldung:

argument of type 'int (Crasynth::)(jack_nframes_type_t)(void*) does not match 'int (*)(jack_nframes_t, void*)'

Ich bin schon ganz schön verzweifelt und googlen hat mir nichts gebracht, außer den Stichworten 'extern' und 'Templates', die ich aber nicht richtig verstehe.


Code:
#include ...
#include <jack/jack.h>

extern "C" int process (jack_nframes_t nframes, void *arg);

using namespace std;

class Crasynth{
	private:...

	
	public:
                int                   create_client(...); //Hilfsfunktion zur Initialisierung
		int 			process (jack_nframes_t, void*); //Soll Callback werden
		Crasynth();
		~Crasynth();
	
}; // Ende der Deklaration von Crasynth

//-------------------------------------------------------------------------------------------------------------

int Crasynth::process (jack_nframes_t nframes, void *arg){
	... 
}

jack_client_t Crasynth::create_client(...){
      ...
      return jack_client;
}

// MAIN
int main(){
	const char *client_name="Crasynth\n";
	Crasynth clientObj; //mein Objekt
        jack_client_t jackClient; //ein Client, den der Server schluckt

	jackClient= clientObj.createClient(...);

	jack_set_process_callback(jack_client, process, 0);
        /* Callback setzen geht nicht, weil C keine Memberfunktionen akzeptiert*/

	while(1);
}

Ich weiß wirklich nicht, was ich tu soll. Alles in C schreiben wäre eine unschöne Möglichkeit und stellt für mich keinen Ausweg dar. Ich muss C++ lernen!

Ich bin für jeden Hilfsversuch dankbar!


Viele Grüße
Andreas
 
Hallo Andreas,
Klassenmethoden können nur als Callback-Funktionen verwendet werden, wenn sie als "static" deklariert werden. Ansonsten passen die Aufrufkonventionen nicht zusammen.

Gruß
MCoder
 
Hi.

So wie es aussieht kannst du ja einen beliebigen Parameter beim registrieren der Callbackfunktion mitgeben.

So könntest du eine Wrapperfunktion schreiben:
C++:
int Crasynth_process(jack_nframes_t frames, void* data) {
  Crasynth* obj = reinterpret_cast<Crasynth*>(data);

  return obj->process(frames);
}
...
Crasynth clientObj; //mein Objekt

// registrieren:
jack_set_process_callback(jack_client, &Crasynth_process, &clientObj);
Gruß
 
Danke! Das funktioniert tatsächlich gut. Ich habe die Wrapper Funktion anschließend selbst noch in mein Objekt "integriert". Dazu musste ich sie dann allerdings static machen, was ja nicht störend ist.

Gelöst! und sehr geholfen...

Grüße.
 
Zurück