Forum Clubic

[c++] Problème avec CreateThread

Bonjour à tous, voilà ce que je code:

DWORD WINAPI CMyDialog::MonThread(LPVOID lParam)
{
char *intf = (char *)lParam;
initComm(TCP,intf,(char *)HTI_BOOTABLE);
return 0;
}

et pour le CreateThread:
CreateThread(NULL,NULL,MonThread,(LPVOID)intf,0,&dwThreadId);

mais quand je compile, ça me dit:
error C2664: ‘CreateThread’ : cannot convert parameter 3 from ‘unsigned long (void *)’ to ‘unsigned long (__stdcall *)(void *)’

je pige vraiment pas d’où vient le problème, car OK je suis pas un dieu du C++, mais dans tous les forums où je me suis balader, ils disent de faire comme ça…
Donc si quelqu’un a une idée pour résoudre ça, ça serait cool!
Merci d’avance
JiB

ps: je code sous visual c++.

[cpp]
static DWORD WINAPI CMyDialog::MonThread(LPVOID lParam)
{
char *intf = (char *)lParam;
initComm(TCP,intf,(char *)HTI_BOOTABLE);
return 0;
}
[/cpp]

Merci, je regardera ça demain voir si ça marche.

Il y a un problème dans ta réponse, karlkox. Le qualificateur “static” ne doit pas être spécifié sur la définition mais plutôt sur la déclaration de la fonction. Ceci ne fonctionnerait que si tu écrivait le corps de ta fonction en inline dans ta classe, ce qu’il faut impérativement éviter de faire car étant une très mauvaise pratique. Ainsi on aura plutot ceci :

[cpp]class CMyDialog
{
// …
static DWORD WINAPI MyThread(LPVOID lParam);
// …
};

DWORD WINAPI CMyDialog::MyThread(LPVOID lParam)
{
// …
return 0;
}
[/cpp]

Comme d’habitude, il vaut mieux éviter le franglais dans le code :slight_smile:

Autre chose et pour expliquer le comportement du compilateur sur l’utilisation de CreateThread avec une fonction membre “instance”, CreateThread ne peut prendre que des pointeurs sur fonction membre statiques, c’est à dire qui ne prennent pas de contexte.

Ce que je te conseille de faire dans ce cas, c’est de passer le pointeur this dans le paramètre de CreateThread, pour pouvoir le récupérer dans la thread :

[cpp]DWORD WINAPI CMyDialog::MyThread(LPVOID lParam)
{
CMyDialog &dialog = (CMyDialog&)lParam;

// dialog allows access to all member variables

initComm(TCP, dialog._myMember, (char *)HTI_BOOTABLE);
return 0;
}

CMyDialog::CMyDialog()
{
_myMember = 0x1234;
CreateThread(NULL, NULL,M onThread, (LPVOID)this, 0, &dwThreadId);
}
[/cpp]


Jay
{Epitech.}
http://msdn.labtech.epitech.net/blogs

lol ! oui … en même temps, une nuite blanche derriere, ca aide pas à la compréhension :stuck_out_tongue:

Merci pour vos réponses!
j’avais vu que mettre le static ne marchait pas; mais en déclarant la fonction à l’extérieur de la classe ça fonctionne.
Le seul problème qui me reste c’est le passage de paramètre, mais j’ai bon espoir !!!

Tu ne pourras pas passer d’autres paramètres que le simple void* qui est disponible avec CreateThread. Je te conseille donc d’utiliser les variables membre de ton instance pour passer des paramètres et d’utiliser le pointeur this pour retrouver ces données, comme dans l’exemple que j’ai donné précédemment.


Jay
{Epitech.}
http://msdn.labtech.epitech.net/blogs

en fait j’ai juste transtypé ce que je voulais en LPVOID et ça marche nickel!

moi j’ai toujours un soucis sur createthread…

voilà j’ai acheté la bible du programmeur qui contenait un cdrom je programme sous visual c++ et la partie sur les thread deconne un peu…

il contient :

Ce fichier CPP:

#include <windows.h>
#include "generic.h"

HINSTANCE hInst; // Instance courante.

LPCTSTR lpszAppName = "MyApp";
LPCTSTR lpszTitle = "Mon Application";

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASS wc;

// Enregistrer la classe de fenêtre de l’application principale.
// …
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, lpszAppName );
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;

RegisterClass( &wc );

hInst = hInstance;

// Créer la fenêtre principale.
//…
hWnd = CreateWindow( lpszAppName,
lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
NULL,
NULL,
hInstance,
NULL
);

if ( !hWnd )
return( FALSE );

ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );

while( GetMessage( &msg, NULL, 0, 0) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}

return( msg.wParam );
}

LRESULT CALLBACK About( HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return (TRUE);

   case WM_COMMAND:                              
           if (   LOWORD(wParam) == IDOK         
               || LOWORD(wParam) == IDCANCEL)    
           {
                   EndDialog(hDlg, TRUE);        
                   return (TRUE);
           }
           break;

}

return (FALSE);
}

////////////// ensuite ce fichier CPP

#include "genstub.cpp"

// C’est une procédure de thread fils qui attend un sémaphore,
// le garde cinq secondes et rel^che le sémaphore.
// Les threads qui ne peuvent accéder aux sémaphores attendront
// la fin des autres threads.
DWORD WINAPI ChildThreadProc( LPVOID parametre )
{
HWND hWnd= (HWND) parametre;
TCHAR szBuffer[256]; // tampon
long lSemCount = 0; // compteur du sémaphore
HANDLE hSemaphore = OpenSemaphore( SYNCHRONIZE, FALSE, “TEST_SEMAPHORE” );
wsprintf( szBuffer,“Thread %x en attente du sémaphore %x”,
GetCurrentThreadId( ), hSemaphore );
SendMessage( hWnd, WM_USER, 0, (LPARAM) szBuffer );
// Attente du signalement du sémaphore
WaitForSingleObject( hSemaphore, INFINITE );
wsprintf( szBuffer,“Thread %x a obtenu le sémaphore”, GetCurrentThreadId( ) );
SendMessage( hWnd, WM_USER, 0, (LPARAM) szBuffer );
Sleep( 5000 );
// Relâcher le sémaphore
ReleaseSemaphore( hSemaphore, 1, &lSemCount );
wsprintf( szBuffer,“Thread %x a terminé avec le sémaphore. Son compteur était %ld.”,
GetCurrentThreadId( ), lSemCount );
SendMessage( hWnd, WM_USER, 0, (LPARAM) szBuffer );
CloseHandle( hSemaphore );
ExitThread( TRUE );
return 0;
}

// procédure de messages Windows
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HANDLE hSemaphore = 0;

switch (uMsg)
{
case WM_CREATE:
	hSemaphore = CreateSemaphore( NULL, 4, 4, &quot;TEST_SEMAPHORE&quot; );
	return DefWindowProc( hWnd, uMsg, wParam, lParam );
case WM_COMMAND:       // traite les éléments de menu
	switch ( LOWORD( wParam )  )
	{
	case IDM_TEST:     // démarre un thread
		{
			DWORD dwChildId;
			CreateThread( NULL, 0, ChildThreadProc, (LPVOID)hWnd, 0, &amp;dwChildId );
		}
		break;
	case IDM_EXIT:
		DestroyWindow( hWnd );
		break;
	}
	break;
	case WM_USER:
		{
			// Message pour afficher les actions de synchronisation
			TCHAR szBuffer[101];
			static int row = 0;
			static int msg_num = 1;
			HDC hDC = GetDC( hWnd );
			FillMemory( szBuffer, 100, 32 );
			TextOut( hDC, 0, row, szBuffer, 100 );
			wsprintf( szBuffer, &quot;%3d: %s&quot;, msg_num++, (LPTSTR)lParam );
			TextOut( hDC, 0, row, szBuffer, lstrlen( szBuffer ) );
			if ( row &gt; 200 )
				row = 0;
			else
				row += 20;
			ReleaseDC( hWnd, hDC );
		}
		break;
	case WM_DESTROY:
		if ( hSemaphore )
			CloseHandle( hSemaphore );
		PostQuitMessage( 0 );
		break;
	default:
		return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
return NULL;

}

////////le fichier d’entete:

#define IDM_EXIT 100
#define IDM_TEST 200
#define IDM_ABOUT 300

#define DLG_VERFIRST 400
#define DLG_VERLAST 404

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM);

le fichier RC n’est pas utile:

mais à la compilation

--------------------Configuration: test5 - Win32 Debug--------------------
Compiling…
genstub.cpp
Skipping… (no relevant changes detected)
Simple_Thread.cpp
Linking…
Simple_Thread.obj : error LNK2005: WinMain@16 already defined in genstub.obj
Simple_Thread.obj : error LNK2005: "long stdcall About(struct HWND *,unsigned int,unsigned int,long)" (?About@@YGJPAUHWND
_@@IIJ@Z) already defined in genstub.obj
Simple_Thread.obj : error LNK2005: "char const * const lpszTitle" (?lpszTitle@@3PBDB) already defined in genstub.obj
Simple_Thread.obj : error LNK2005: "char const * const lpszAppName" (?lpszAppName@@3PBDB) already defined in genstub.obj
Simple_Thread.obj : error LNK2005: "struct HINSTANCE__ * hInst" (?hInst@@3PAUHINSTANCE__@@A) already defined in genstub.obj
Simple_Thread.obj : error LNK2001: unresolved external symbol "int __cdecl RegisterWin95(struct tagWNDCLASSA const *)" (?RegisterWin95@@YAHPBUtagWNDCLASSA@@@Z)
Debug/test5.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

test5.exe - 7 error(s), 0 warning(s)

merci de m’aider…

non c bon j’ai vu mon soucis … :clap:

c juste que dans mon projet c++ j’ai ajouté les 2 fichiers CPP