pthread_create mit Funktionszeiger als Argument
-
Hallo,
ich habe folgende Funktion:void qfFunc(time_t timestamp) { cout << timestamp << endl; }Diese Funktion wird als Zeiger an eine Klasse übergeben (Konstruktor)
meineKlasse::meineKlasse(string tName, string tPath, void (*queryFunction) (time_t)) { pFunc = queryFunction; //pFunc ist private } meineKlasse c = meineKlasse("123", "456", qfFunc);In der Methode runQuery soll dann ein Thread mit der übergebenen Funktion gestartet werden.
void meineKlasse::runQuery(time_t ts) { pthread_create(&t1, NULL, (void (*)(time_t))pFunc, ts);//t1 ist auch private } c.runQuery(12345);Beim Kompilieren kriege ich aber folgende Fehlermeldung:
error: invalid conversion from 'void (*)(time_t) {aka void (*)(long int)}' to 'void* (*)(void*)' [-fpermissive] pthread_create(&t1, NULL, (void (*)(time_t))pFunc, ts); ^Kann mir jemand sagen wie ich das beheben kann?
Vielen Dank!
-
Die Funktionssignatur stimmt nicht. Der Parameter der Funktion, die Du
pthread_createübergibst, muss als Parameter einenvoid*haben und einenvoid*zurück geben. Eine Konvertierung von Deiner Funktion ist nicht möglich.
-
Die Funktion erwartet void* als Argument.
Deine Funktion qfFunc time_t.
Du musst in qfFunc void* nehmen und das casten.Edit: Kannst du aber auch ganz einfach automatisieren.
template <void(*fnc)(time_t)> void trampoline(void *arg) { fnc(*static_cast<time_t*>(arg)); } meineKlasse::meineKlasse(string tName, string tPath, void (*queryFunction) (time_t)) { pFunc = &trampoline<queryFunction>; //pFunc ist private } void meineKlasse::runQuery(time_t ts) { pthread_create(&t1, NULL, pFunc, &ts);//t1 ist auch private }(ungetestet)
-
Danke für die Antwort Nathan, aber leider wirft die Zeile
pFunc = &trampoline<queryFunction>;die Fehlermeldung
error: 'queryFunction' is not a valid template argument for type 'void (*)(time_t) {aka void (*)(long int)}' pFunc = &trampoline<queryFunction>; ^error: it must be the address of a function with external linkageaus. Habe noch nie mit Templates gearbeitet, deswegen fällt es mir schwer hier den Fehler zu erkennen..
-
Natürlich, geht so nicht.
Du musst aus dem Konstruktor auch noch ein Template machen:template <void (*queryFunction)(time_t)> meineKlasse(string tName, string tPath) { pFunc = &trampoline<queryFunction>; //pFunc ist private }Ich kann allerdings auch schnell noch etwas schreiben um das zu vermeiden, moment.
Edit: Hier, wesentlich simpler, musst an den anderen Funktionen gegenüber dem Einstiegspost nichts ändern.
struct trampoline_info { void (*fnc)(time_t); time_t arg; }; void trampoline(void *arg) { auto info = *static_cast<trampoline_info*>(arg); info.fnc(info.arg); } void meineKlasse::runQuery(time_t ts) { trampoline_info info{pFunc, ts}; pthread_create(&t1, NULL, &trampoline, &info);//t1 ist auch private }
-
Hi,
Nathan schrieb:
Edit: Hier, wesentlich simpler, musst an den anderen Funktionen gegenüber dem Einstiegspost nichts ändern.
struct trampoline_info { void (*fnc)(time_t); time_t arg; }; void trampoline(void *arg) { auto info = *static_cast<trampoline_info*>(arg); info.fnc(info.arg); } void meineKlasse::runQuery(time_t ts) { trampoline_info info{pFunc, ts}; pthread_create(&t1, NULL, &trampoline, &info);//t1 ist auch private }Aber hier ist doch das Problem das 'info' zerstoert wird nachdem runQuery fertig ist und der zweite Thread noch darauf zugreift.
Solle man wenn dann nicht eher sowas nutzen:
void trampoline(void *arg) { std::unique_ptr<trampoline_info> info( static_cast<trampoline_info*>(arg)); info->fnc(info->arg); } void meineKlasse::runQuery(time_t ts) { auto info = new trampoline_info{pFunc, ts}; pthread_create(&t1, NULL, &trampoline, info);//t1 ist auch private }
-
stuxn schrieb:
Hi,
Nathan schrieb:
Edit: Hier, wesentlich simpler, musst an den anderen Funktionen gegenüber dem Einstiegspost nichts ändern.
struct trampoline_info { void (*fnc)(time_t); time_t arg; }; void trampoline(void *arg) { auto info = *static_cast<trampoline_info*>(arg); info.fnc(info.arg); } void meineKlasse::runQuery(time_t ts) { trampoline_info info{pFunc, ts}; pthread_create(&t1, NULL, &trampoline, &info);//t1 ist auch private }Aber hier ist doch das Problem das 'info' zerstoert wird nachdem runQuery fertig ist und der zweite Thread noch darauf zugreift.
Klar, das ist ja ein Thread.
Dumm von mir.
Entweder deine Lösung, oder trampoline_info in die Klasse packen, wenn die Klasse länger lebt als der Thread.
-
Benutze C++11 std::thread oder boost::thread.