Mit CreateThread Klassenmethode aufrufen
-
Hallo,
ich möchte jetzt mit der Funktion CreateThread() aus dem Hauptprogramm heraus eine Klassenmethode aufrufen.
int main(int argc, char **argv) { test h; HANDLE hThread[test::MAX_THREADS]; DWORD dwThreadID[test::MAX_THREADS]; h.intialize(argv[1], atoi(argv[2])); for (int i = 0; i < atoi(argv[4]); i++) hThread[i] = CreateThread(0, 0, test::meineFunc, argv[3], 0, &dwThreadID[i]); return 0; }
Kann mir jmd. sagen wie ich das machen muss? Ich finde über google auch nicht wirklich hilfreiche Beispiele.
-
Du brauchst eine Trampolin-Funktion.
Entweder eine freie Funktion (geht garantiert auf allen Compilern), oder eine statische Memberfunktion (geht zumindest mit MSVC, und vermutlich auch mit allen existierenden Compilern).Diese statische Memberfunktion muss einen void* als Parameter nehmen.
Den Wert der da übergeben werden soll kannst du ja bei CreateThread/_beginthreadex mitgeben.Schlauerweise gibt man "this" als Parameter mit, castet dann in der Trampolin-Funktion von void* zurück auf den Klassentyp, und ruft über diesen Zeiger dann die nicht-statische Memberfunktion auf.
-
hustbaer schrieb:
Entweder eine freie Funktion (geht garantiert auf allen Compilern), oder eine statische Memberfunktion (geht zumindest mit MSVC, und vermutlich auch mit allen existierenden Compilern).
Afaik garantiert der C++ Standard, dass ein Pointer auf eine statische Memberfunktion ein normaler Function Pointer ist (§13.4/3), das muss also auf allen konformen Compilern funktionieren.
-
Uff, ja, haste auch wieder Recht
(Also ich weiss nicht ob der Standard das garantiert, aber ich gehe einfach mal davon aus dass du Recht hast)Ich hatte in Erinnerung dass da irgendwas war...
Und das "Irgendwas" war:
Die WinAPI verwendet ne spezielle Calling-Convention für Thread-Funktionen, nämlich
__stdcall
.
Theoretisch wäre es jetzt möglich dass ein Compiler__stdcall
unterstützt (weil man ihn sonst unter Windows nicht ordentlich verwenden kann), aber nur für freie Funktionen.
Das wäre allerdings total beknackt, d.h. man kann davon ausgehen dass es nie einen solchen Compiler geben wird.@Celebrariel
Achja nochwas...Du kannst auch Boost.Thread + Boost.Bind verwenden - damit lässt sich mMn. wesentlich angenehmer arbeiten als mit der MFC/WinAPI.
Wobei es wahrscheinlich Overkill wäre die Boost nur dafür einzubinden. Andrerseits gibt es in der Boost auch noch viele viele andere nützliche Dinge...
-
hustbaer schrieb:
Theoretisch wäre es jetzt möglich dass ein Compiler
__stdcall
unterstützt (weil man ihn sonst unter Windows nicht ordentlich verwenden kann), aber nur für freie Funktionen.
Das wäre allerdings total beknackt, d.h. man kann davon ausgehen dass es nie einen solchen Compiler geben wird.Achso das meintest du. An das hab ich gar nicht gedacht, ich dachte du bist dir unsicher ob es garantiert ist, dass ein Zeiger auf eine statische Methode ein normaler Function Pointer ist, oder ob das vielleicht eher nur implementation defined aber de-facto Standard ist. Da ich mir selbst nicht so sicher war, hab ich schnell nachgeschaut (kann natürlich sein dass ich mich irre, den Standard zu interpretieren ist eine eigene Wissenschaft)...
-
Ich hatte nur mehr im Hinterkopf "da war was, was mit statischen Memberfunktionen nicht garantiert ist".
Ist mir dann erst später eingefallen worum es dabei ging.Aber wie gesagt: wäre total beknackt, kann man also ignorieren.
-
hustbaer schrieb:
Aber wie gesagt: wäre total beknackt, kann man also ignorieren.
In der Tat.
-
hustbaer schrieb:
Schlauerweise gibt man "this" als Parameter mit, castet dann in der Trampolin-Funktion von void* zurück auf den Klassentyp, und ruft über diesen Zeiger dann die nicht-statische Memberfunktion auf.
Du meinst also, dass ich in der "Trampolinfunktion" CreateThread aufrufen soll?
Also in etwa sowas?DWORD WINAPI test::wrapper(void *) { HANDLE hThread[test::MAX_THREADS]; DWORD dwThreadID[test::MAX_THREADS]; hThread[0] = CreateThread(0, 0, meineFunc, 0, 0, &dwThreadID[0]); }
Nur was meinst du genau mit dem this-Zeiger und wo ich den übergeben soll.
Sorry, ich bin noch relativ neu mit C++ unterwegs.
-
Nein, die Trampolin-Funktion verwendest du als "Thread-Function":
void blah() { Foo* foo = new Foo(); CreateThread(..., trampoline_function, /*adresse des Objekts als "param" übergeben*/ foo, ...); } UINT trampoline_function(void* param) { Foo* foo = static_cast<Foo*>(param); // *HÜPF* return foo->the_real_thread_function(); }