In examples on the web, calls to CreateThread typically pass a pointer to a struct for LPVOID lpParameter, and you use that pointer to access the struct itself.
#include <Windows.h>
#include <stdio.h>
struct Point
{
float x,y,z ;
} ;
DWORD WINAPI threadStartPoint( LPVOID data )
{
Sleep( 1000 ) ;
Point *p = (Point*)data ;
printf( "%f %f %f\n", p->x, p->y, p->z ) ;
puts( "Thread job done" ) ;
return 0 ;
}
// From main
int main()
{
DWORD threadId ;
Point p ;
p.x=2, p.y=3, p.z=4 ;
HANDLE handle = CreateThread( 0, 0,
threadStartPoint,
(LPVOID)&p,
0, // ?? I think I should be using this parameter</b>
&threadId
) ;
if( !handle )
{
// Thread creation failed
puts( "start fail\n" );
}
else
{
printf( "started on threadid=%d\n", threadId ) ;
}
WaitForSingleObject( handle, 2000 ) ; // wait up to 2000 ms for the other thread to complete before moving on
puts( "main thread Exiting.." ) ;
//system( "pause" ) ;
}
I’m finding this to be somewhat of an inconvenience, since you have to make sure that struct exists, and make sure it is properly destroyed when the thread is finished executing.
I’d like to start my thread, but passing normal stack arguments ie automatic variables, or perhaps, the struct itself to the thread start routine:
DWORD threadStartPointFuncStyleIWant( Data d ) ;
So my questions are really:
- For a thread start point (CreateThread), are we restricted to a function with prototype of the form:
DWORD validThreadFunc( LPVOID pParamStruct ) ;
- Or can we start a thread on functions like
DWORD threadFunc1( int p1, int p2 ) ; DWORD threadFunc2( Data d ) ;
CreateThreadaccepts only one type of function, the one that takes a singleLPVOIDparameter. There’s no way to communicate to kernel32.dll, which is the code that calls your thread function, that it should call it with any other parameter list. The kernel always calls the function the same way.You’ll just have to continue doing it the same way everyone else does. Allocate the structure on the heap, pass the pointer to your thread routine, and then free it before returning from your thread routine. That is, ownership passes from the originating thread to the new thread. Once the new thread gets ownership, you can use a smart pointer like
shared_ptrto make sure it gets freed however you leave the thread.You’re welcome to pass another function pointer in that struct, or pass an object with methods of its own. Then your thread procedure becomes nothing more than something to unpack the
LPVOIDparameter and dispatch to the other function pointer or method, where you do all the real work for the thread.