C++ member Methode als Callback-Funktion übergeben
-
Hallo zusammen,
ich versuche eine Klasse zuschreiben in der sich eine Callback Funktion
befindet. Ich möchte sie als nicht-statischen deklariert,weil ich in der
Callback-Funktion die anderen member Funktion und die andern Membern
Werte zugreifen möchte. meine Frage Ob es möglich ist, denn die meisten
beispiele und mein Programm kriege ich zum laufen nur wenn die
Callbackfunktion als globale Funktion definiere oder als statische
Funktion.Hier ist mein Code:
myclass.hpp
//void * callBackFunction(void *arg) ; //callback als globale Funktion class myClass { public: myClass(); void flaeche(); void creatTreads(); void* callBackFunction(void *arg); //static void* callBackFunction(void *arg); vtkSmartPointer <vtkMultiThreader> threads; private: double breite ; double laenge; };
myclass.cpp
myClass::myClass(){ this->laenge = 0.0; this->breite = 0.0; } void* myClass::callBackFunction(void *arg ){ // explicitly cast to a pointer int id = *((int *)arg); // process ID myClass *mySelf = (myClass*) arg; mySelf->flaeche(); std::cout<<"thread Function: process :prozess.id="<<id<<std::endl; } void myClass::flaeche(){ double sr =this->laenge * this->breite; cout<<"flaeche():sr ="<<sr<< "lange="<<this->laenge<<"breite ="<<this->breit<<endl; } void myClass::creatTreads(){ this->laenge =10.5; this->breite = 10.5; threads = vtkSmartPointer<vtkMultiThreader>::New(); cout << "Initialization DONE" << endl; int thID = 0; thID = threads->SpawnThread((vtkThreadFunctionType)(*callBackFunction), &thID); } int main(int argc, char *argv[]) { myClass C; C.creatTreads();
Allerdings erhalte ich dann einen Fehler:
:104:57: error: invalid use of member function (did you forget the ‘()’ ?)
Wie könnte man diese Problem umgehen? Die CallBackfunktion als static
deklarieren aber wie kann man auf den aktullen Object zugreifen oder
gibts auch andere Lösungen?Danke schön mal im Voraus
Sokratss
-
Wenn du Memberfunktionen binden willst, brauchst du Memberfunktionszeiger. Das Standardnachschlagewerk, wenns um alle möglichen Varianten von Funktionszeigern geht:
http://www.newty.de/fpt/index.htmlIn C++ kannst du allerdings die viel mächtigere Klasse
std::function
nehmen, an die du mitstd::bind()
und Lambda-Ausdrücken so gut wie alles binden kannst. Schau dazu vielleicht auf www.cppreference.com nach.
-
Die Frage ist wie immer: Memberfunktion von welchem Objekt? Deine Erklärung, dass es auch eine Option wäre, die gleiche Funktion static oder global zu machen ist da sehr verwirrend, denn diese Funktionen wären schließlich auch ohne ein Objekt der Klasse aufrufbar.
Jedenfalls muss dein Caller wissen, auf welchem Objekt er die Memberfunktion aufrufen soll. Falls dein Caller das nicht weiß, sondern bloß ein allgemeines, aufrufbares Objekt erwartet, dann kannst du auch das gewünschte Objekt und die gewünschte Memberfunktion zu einem Paket zusammenschnüren und übergeben. Die Standardbibliothek kennt das ab C++11 fix und fertig als std::bind. Vor C++11 gibt's da auch Methoden für (Header
functional
), ist aber ziemlich unschön zu bedienen, so dass man ohne C++11 wohl besser mal boost::bind angucken sollte.Ein Beispiel (zusammengefügt von en.cppreference.com):
#include <iostream> #include <functional> struct Foo { void print_sum(int n1, int n2) { std::cout << n1+n2 << '\n'; } int data = 10; }; int main() { using namespace std::placeholders; //for _1, _2, _3... // bind to a member function Foo foo; auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1); f3(5); }
-
[quote="SeppJ"]Die Frage ist wie immer: Memberfunktion von welchem Objekt?
ich möchte auf das gleiche Object zugreiffen, ich habe das programm ein beischen geändert, nun habe ich cid Callbackfuntion doch als static Methode deklariert und wolte die aktuelle Object als Parmeter für sie übergebenclass myClass { public: myClass(); void flaeche(); vtkSmartPointer<vtkMultiThreader> threads; void creatTreads(); static void callBackFunction(myClass *arg); private: double breite ; double laenge; }; myClass::myClass(){ this->laenge = 0.0; this->breite = 0.0; } void myClass::callBackFunction(myClass *arg ){ myClass *mySelf = (myClass*) arg; mySelf->flaeche(); boost::bind(&myClass::flaeche, &mySelf); } void myClass::flaeche(){ double sr =this->laenge * this->breite; cout<<"flaeche():sr ="<<sr<< "lange="<<this->laenge<<"breite ="<<this->breite<<endl; } void myClass::creatTreads(){ this->laenge =10.5; this->breite = 10.5; vtkSmartPointer<vtkMultiThreader> threads = vtkSmartPointer<vtkMultiThreader>::New(); int thID = 0; thID = threads->SpawnThread((vtkThreadFunctionType)(callBackFunction)(this), &thID); }
aber da schmeiß mir die Complier folgende fehler:
: error: void value not ignored as it ought to be
-
Hallo,
laut SpawnThread kannst du als 2. Parameter ein beliebiges Objekt übergeben (d.h. this als Zeiger auf deine Klasse):
thID = threads->SpawnThread((vtkThreadFunctionType)callBackFunction, this);
(dein bisheriges Konstrukt ergab überhaupt keinen Sinn...)
-
Hallo,
das habe ich schön probiert aber wie kann ich auf das Object in callbackfunktion
zugreiffen wenn es nicht als parmeter für sie übergeben wird.Th69 schrieb:
thID = threads->SpawnThread((vtkThreadFunctionType)callBackFunction, this);
(dein bisheriges Konstrukt ergab überhaupt keinen Sinn...)
-
Ändere mal deine Callback-Funktion zu
void myClass::callBackFunction(void *arg) // <- Parametertyp ändern { myClass *mySelf = (myClass*) arg; // ... }
-
Th69 schrieb:
Ändere mal deine Callback-Funktion zu
void myClass::callBackFunction(void *arg) // <- Parametertyp ändern { myClass *mySelf = (myClass*) arg; // ... }
Das habe ich doch in mein code die ich oben opostet habe, schon mal versucht, der
erzeugt eine neue object, ich will aber auf den alten bzw gleichen object benutze.void myClass::callBackFunction(myClass *arg ){ myClass *mySelf = (myClass*) arg;
-
Du hast aber
myClass*
als Parameter und nichtvoid*
.Übrigens:
myClass *mySelf = (myClass*) arg;
Hier würde ich C++-Castoperatoren nehmen:
myClass* mySelf = static_cast<myClass*>(arg);
-
ich habe es gerade ausprobiert, es wird immer eine neue Object erzuegt:
void myClass::callBackFunction(void *arg ){ int id = *((int *)arg); // process ID myClass *mySelf = static_cast<myClass*>(arg); mySelf->flaeche();
aber das glaube ich nicht andress seine, die Methode der VtkMultithreader Object
SpawnThread() nur eine Signature einer void Funktion aufrufen kann, dh das object wird nicht mit rübergeben bzw. gespeichert