Archiv verlassen und diese Seite im Standarddesign anzeigen : Pointer auf eine Memberfunktion für thread
Poseidonius
22-07-2006, 17:32
Hallo zusammen,
auf den Verdacht hin, dass meine Vorhaben Unfug ist ... vielen Dank für Eure Nachsicht.
Ich habe ein kleines C-Programm gebastelt, in dem mehrere Threads laufen. Nun wurde das ganze zu unübersichtlich und ich habe versucht es in C++ umzusetzen.
Die Threadfunktionen waren dabei, da pthread_create einen Funktionspointer erwartet als
void * TCP_observer(void *arg){}
definiert. Wie muss ich diese Funktion nun in meine Klasse einbauen, damit der Threadaufruf weiterhin tut?
Wenn ich die Funktion wie folgt anlege
class TCP
{
void *TCP_observer(void *arg);
};
und in main.cpp den Thread einbaue:
TCP tcp_connection;
pthread threadTCP;
pthread_create (&threadTCP, NULL, ?, (void*)&arg);
wie zum Fuchs muss denn dann der Funktionsaufruf anstelle des "?" heissen, ich hatte mir sowas wie
&(tcp_connection.*TCP_observer)
vorgestellt, passt aber nicht. Oder macht man es ganz anders?
locus vivendi
22-07-2006, 18:05
Das ist eine FAQ:
http://www.parashift.com/c++-faq-lite/
Unter Pointer to member functions gucken.
anda_skoa
22-07-2006, 18:25
Also entweder mit einer static Method oder mit einer Funktion im Sourcefile. Letzteres mit einer static Funktion wenn man die Registrierung des Callbacks im selben Sourcefile macht.
class TCP
{
public:
static void TCP_observer(void *arg);
private:
void TCP_observer();
};
void TCP::TCP_observer(void* arg)
{
TCP* tcp = reinterpret_cast<TCP*>(arg);
tcp->TCP_observer();
}
TCP tcp_connection;
pthread threadTCP;
pthread_create (&threadTCP, NULL, tcp_connection::TCP_observer, (void*)&tcp_connection);
Dürfte aber schon ein paarmal in diesem Forum beantwortet worden sein ;)
Ciao,
_
locus vivendi
22-07-2006, 20:01
void TCP::TCP_observer(void* arg)
{
TCP* tcp = reinterpret_cast<TCP*>(arg);
tcp->TCP_observer();
}
Man kann da auch einen static_cast nehmen. Ich bin mir nicht sicher, aber ich habe den Verdacht das der reinterpret_cast auch unportabel ist. Der Standard sagt zwar, dass ein Zeiger auf ein Objekt mit einem reinterpret_cast in einen Zeiger auf ein Objekt mit abweichendem Typ gewandelt werden kann, und das durch die entgegengesetzte Konvertierung wieder derselbe Wert entsteht. Nun benutzt der Standard aber anscheinend den Ausdruck "Zeiger auf Objekt" nicht für den Typ "void*". Mit anderen Worten das Resultat der Konvertierungen wäre nicht spezifiziert.
Noch einmal zur Vorsicht, ich bin mir nicht wirklich sicher ob diese Interpretation korrekt ist. Allerdings ist benutzen von static_cast in jedem Fall OK, denn dafür ist die Konvertierung nach void* und dann zurück explizit im Standard erwähnt.
Poseidonius
23-07-2006, 12:25
Hi,
vielen Dank für eure Antworten, insbesondere das FAQ ist eine gute Hilfe:
Nun muss ich ehrlich zugeben, den Unterschied zwischen den von Euch vorgestellten Methoden via static Memberfunction oder über den Pointer auf eine Memberfuncition nicht so recht verstanden zu habe. Für die Nutzung einer static Funktion brauche ich keine Instanz des Objektes - sprich ich benutze das diese Funktion im ganzen Programm nur ein mal, während ich mit der anderen Methode beliebig viele Instanzen und damit Aufrufe dieser Funktion nutzen kann?
Und dann ist da noch das Problem, dass ich nicht weiss, wie ich die static Memberfunktion in meinen thread-Aufruf reinbekomme. Wenn ich mit
class TCP
{
static void TCP_observer(void *arg);
};
static void TCP_observer(void *arg)
{};
den Aufruf so mache
pthread threadTCP;
pthread_create (&threadTCP, NULL, &TCP::TCP_observer, (void*)&arg);
bekomme ich die Compilermeldung
Fehler: ungültige Umwandlung von void (*) (void *) in void*(*) (void*)
Fehler: Argument 3 von int pthread_crate(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*) wird initialisiert
Wäre für Eure Hilfe sehr dankbar
Noch ein schönes Wochenende
locus vivendi
23-07-2006, 12:56
Nun muss ich ehrlich zugeben, den Unterschied zwischen den von Euch vorgestellten Methoden via static Memberfunction oder über den Pointer auf eine Memberfuncition nicht so recht verstanden zu habe.
Pointer auf Memberfunktion hat glaube ich niemand vorgeschlagen. Das wäre auch umständlich.
Und dann ist da noch das Problem, dass ich nicht weiss wie ich die static Memberfunktion in meinen threadaufruf reinbekomme.
Der Rückgabetyp stimmt nicht. pthread_create erwartet das void* zurückgegeben wird, und dein Funktion gibt gar nichts zurück.
Poseidonius
23-07-2006, 19:18
Ok, auf die Gefahr hin mich voll zum Drops zu machen ...
wenn also die static Funktion einen Rückgabewert hat, zum Beispiel int, wie presse ich diesen dann in den Thread-Start-Aufruf.
Ich hatte mir sowas wie
(void*) & TCP::TCP_observer
gedacht, was aber falsch sein muss, da wieder die "ungültige Umwandlung" kommt. Was ist das überhaupt für ein Konstrukt void * (*) (void *) ???
Vielen Dank für Eure Geduld
locus vivendi
23-07-2006, 19:32
wenn also die static Funktion einen Rückgabewert hat, zum Beispiel int, wie presse ich diesen dann in den Thread-Start-Aufruf.
So ohne weiteres gar nicht. pthread_create erwartert einen Zeiger auf eine Funktion die eine void* zurückgibt und genau einen void* entgegennimmt (also den deklarierten Typ "void* (*)(void*)"). Es geht nichts anderes. Das bedeutet für dich, dass wenn du eine Funktion hast deren Typ abweicht, du diese inklusive Rückgabewert und Argument verpacken musst. Du kannst ja mal in eine Bibliothek gucken die Thread-Erzeugung kapselt, dann sollte das klarer werden, wenn es das jetzt noch nicht ist. (Nur als Beispiel in Commonc++, die ist noch einigermaßen übersichtlich). Das hat übrigens nicht viel mit C++ zu tun. In C müsstest du genauso verfahren.
Noch zum reinterpret_cast Vs. static_cast: O'Reilis Buch C++ in a Nutshell sagt auch das man da static_cast nehmen soll. reinterpret_cast ist eher für so kranke sachen gedacht wie: Klasseninstanz A in Klasseninstanz B umwandeln. Sowas kann schlimm in die Hose gehn und sollte man nur machen wenn man weiß was man tut (und auch dann ists nicht ratsahm).
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.