CreateThread Fehler

hallo

ich möchte eine funktion per createthread aufrufen
die funktion heißt
Code:
void ProcessExplorerFunc(int port, char ipadress2[])

so in der art stell ich mir das vor:
Code:
CreateThread(NULL,0, (LPTHREAD_START_ROUTINE) ProcessExplorerFunc,keine ahnung,0,0);

aber ich weiß nicht wie ich 2 parameter an die funktion vergeben kann und außerdem kommt noch ein solcher error:
error C2440: 'initializing' : '' kann nicht in 'unsigned long (__stdcall *)(void *)' konvertiert werden
 
du kannst aus dieser funktion nicht direkt einen thread erstellen, da eine LPTHREAD_START_ROUTINE immer ein DWORD zurueckgeben muss und nur einen DWORD als parameter nimmt. du muesstest das ganze als in eine extra funktion packen:
Code:
DWORD WINAPI ThreadFunktion(LPVOID lpParam) {
ProcessExplorerFunc(port, ipadress)
}
und in deiner WinMain etc.: dann
DWORD dwTId;
HANDLE hThread;
hThread = CreateThread(NULL, 0,ThreadFunktion,NULL, 0, &dwTId);

Hier details zu der API

mfg jacky
 
Original von heinzelJacKy
du kannst aus dieser funktion nicht direkt einen thread erstellen, da eine LPTHREAD_START_ROUTINE immer ein DWORD zurueckgeben muss und nur einen DWORD als parameter nimmt. du muesstest das ganze als in eine extra funktion packen:
Code:
DWORD WINAPI ThreadFunktion(LPVOID lpParam) {
ProcessExplorerFunc(port, ipadress)
}
und in deiner WinMain etc.: dann
DWORD dwTId;
HANDLE hThread;
hThread = CreateThread(NULL, 0,ThreadFunktion,NULL, 0, &dwTId);

Hier details zu der API

mfg jacky

Einfacher wäre, einen Zeiger auf ein struct mit den ganzen Parametern zu übergeben, da man sich dann die zweite Funktion spart. Ungefähr so:
Code:
struct DATA {
int port;
char *ip_addr;
};

...
DWORD WINAPI ProcessExplorerFunc(DATA *d)
{
  x = d->port; //nur ein Bsp.
}
..
DATA *d = (DATA*)malloc(sizeof(DATA)); //NICHT auf dem Stack anlegen
d->port = 0x1234;
d->ip_addr = "127.0.0.1"; //bei Strings aufpassen, dass diese nicht auf dem Stack liegen wie z.B. bei char buf[300] o.ä., da nur ein Pointer zu dem String sich in der Struktur befindet
CreateThread(0,0,ProcessExplorerFunc,d,0,0);
 
wenn ich dein beispiel nutze (ich habe den namen der klasse von DATA in MyData geändert) dann sagt der compiler:
error C2664: 'CreateThread' : Konvertierung des Parameters 3 von 'unsigned long (struct MyData)' in 'unsigned long (__stdcall *)(void *)' nicht moeglich

edit: so ich benutze jetzt eine modifiezierung des codes aus der msdn.
wenn ich das in einem exe project mache funktioniert das einwandfrei aber in dieser dll geht es nicht:
Code:
DWORD WINAPI TestFunc( LPVOID lpParam)
{
	MessageBox(NULL,"lol","BIX",MB_OK);
	return 0;
}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
	CreateThread(0,0,TestFunc,0,0,0);
        return;
}

wieso zeigt der keine message box an?!
 
dein fehler mit der konvertierung hört sich eher so an, als ob du beim funktionsaufruf deine parameter vertauscht hättest und an dritter stelle statt deiner funktion deinen parameter angegeben hast, 'unsigned long (__stdcall *)(void *)' ist nämlich der typedef fuer LPTHREAD_START_ROUTINE und an der stelle sollte dann folglich eine funktionsaddresse stehen..

zum edit:
kann sein dass dein compiler einen typecast verlangt, manche sind da ein bisschen zickig, also so z.b.:
Code:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestFunc, 0, 0);

ist deine "ProcessExplorerFunc()" selber geschrieben oder ist die aus irgend einer bibliothek?
 
nein die ist selber geschrieben, aber besteht im moment nur aus einer message box

zu dem hier
Code:
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestFunc, 0, 0);

auch so funktioniert es nicht, eg sollte es auch ohne typecast gehen
 
aso jetz, du hast einfach nen parameter zu wenig:
Code:
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter,
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);

mit dem letzten parameter muesste es dann so aussehen:

Code:
DWORD dwTID;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)TestFunc, 0, 0, &dwTID);

wenn deine ProcessExplorer() selber geschrieben ist, ist wohl wirklich die methode von lesco besser. dachte das ist ne bibliotheksfunktion, die du als thread starten wolltest..
 
Original von NULL!=NULL
wenn ich dein beispiel nutze (ich habe den namen der klasse von DATA in MyData geändert) dann sagt der compiler:
error C2664: 'CreateThread' : Konvertierung des Parameters 3 von 'unsigned long (struct MyData)' in 'unsigned long (__stdcall *)(void *)' nicht moeglich

Je nach Compiler, muss man den Parameter noch entsprechend casten, wobei aus deiner Fehlermeldung hervorgeht, dass du als Parameter der Funktion für den Thread die ganze Struktur statt einen Zeiger auf die Struktur erwartest.
Hier ist ein komplettes Beispiel, was bei mir funktioniert:
Code:
#include <windows.h>

struct DATA {
	int port;
	char *ip_addr;
};

DWORD WINAPI ProcessExplorerFunc(DATA *d)
{
	MessageBox(0,d->ip_addr,0,0);
//Daran denken, den Speicher für die Struktur wieder freizugeben
	return 0;
}

int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	DATA *d = (DATA*)malloc(sizeof(DATA)); 
	d->port = 0x1234;
	d->ip_addr = "127.0.0.1";
	CreateThread(0,0,(LPTHREAD_START_ROUTINE)ProcessExplorerFunc,d,0,0);
	Sleep(5000);
	return 0;
}
 
@Lesco

gehört zwar nicht zum Tema, aber:

Benutze ich dein Beispiel in meinem Programm, bekomme ich folgende Meldung:

Code:
'overloaded-function' kann nicht in 'LPTHREAD_START_ROUTINE' konvertiert werden
        Keine Funktion mit diesem Namen im Gültigkeitsbereich stimmt mit dem Zieltyp überein

Programm:

Code:
struct DATA 
{
	int port;
	char *ip_addr;
};
ThreadTest(DATA *d)
{
	MessageBox( NULL, "TEST", "TEST", MessageBoxButtons::OK );
	return 0;
}
[...]

DATA *d = (DATA*)malloc(sizeof(DATA));
d->port = 1234;
d->ip_addr = "127.0.0.1";
CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)ThreadTest, d, 0, 0 );

Der Code befindet sich innerhalb einer Klasse:

Code:
public __gc class Form1 : public System::Windows::Forms::Form
{
public:
...
protected:
...
private:

// Hier ist dann der Code (der Aufruf natürlich in einer Extra Funktion)
};
[CODE]
 
Methoden lassen sich leider nicht als Parameter für CreateThread() übergeben, da diese mit der __thiscall-Konvention aufgerufen werden und die CreateThread-Funktion eine __stdcall-Funktion erwartet und eine Methode immer nur über die Instanz einer Klasse aufgerufen werden kann . Es gibt keine wirklich schöne Lösung dafür, ein Workaround ist es aber, die betreffende Funktion als "static __stdcall" zu deklarieren und den Zeiger auf das zugehörige Objekt dann anders zu übergeben(z.B. in der Struktur).

Wobei jedoch dein Code sehr nach .net aussieht und es wahrscheinlich ein .net-Äquivalent zu CreateThread() gibt und es dann wahrscheinlich besser wäre, dieses stattdessen zu verwenden.
 
also wenn ich der variable d->ip_addr zb den wert "127.0.0.1" zuweisen will mach ich das so:
d->ip_addr = "127.0.0.1";

aber was ist wenn ich dieser variable den wert einer anderen char[] variable zuweisen will?

wenn ich zb habe:
char test[]="hhuhuh";

und benutze dann strcpy
strcpy(d->ip_addr,test);

dann stürzt das programm ab

auch d->ip_addr = test;

geht nicht
 
Dazu darf das Array nicht auf dem Stack gespeichert werden, da es sonst während der Ausführung des Threads nicht mehr verfügbar ist.
Eine mögliche Lösung wäre es, es auf dem Heap anzulegen:
Code:
DWORD __stdcall ThreadProc(...)
{
   //Benutzung des Elements:
   MessageBox(0,d->ip_addr,0,0);
   //Speicher wieder freigeben:
   delete [] d->ip_addr;
}

....
d->ip_addr = new char[1024];
strcpy(d->ip_addr,"foo");
CreateThread(....);

Alternativ kannst du auch das Array mit in die Struktur packen, allerdings ist dann die Länge der Zeichenkette eingeschränkt.
 
Zurück
Oben