I have a weird bug when I try to use the CreateThread
function. Here's my code:
HANDLE threads[3]; //threads[0] is printer, threads[1] is receiver, [2] is serverconn
DWORD printer_id, receiver_id, serverconn_id;
if(
((threads [0] = CreateThread(NULL, 0, printer_thread, (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
((recv_thread = threads [1] = CreateThread(NULL, 0, receiver_thread, (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
((threads [2] = CreateThread(NULL, 0, serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
)
{
IO_print_line("Initialization error");
return FALSE;
}
printer_thread
, receiver_thread
and serverconn_thread
are functions defined like this:
int serverconn_thread(LPVOID args);
The Visual Studio compiler gives me this error:
Error C2440 'function': cannot convert from 'int (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
And I really don't get it since I think I've done exactly what the official documentation suggests.
And no, changing the thread functions' return type to DWORD
doesn't solve anything, the error only changes to:
Error C2440 'function': cannot convert from 'DWORD (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'
Weird thing is if I change it like this:
if(
((threads [0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &printer_thread, (LPVOID) thread_args, 0, &printer_id)) == NULL) ||
((recv_thread = threads [1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &receiver_thread, (LPVOID) thread_args, 0, &receiver_id)) == NULL) ||
((threads [2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &serverconn_thread, (LPVOID) thread_args, 0, &serverconn_id)) == NULL)
)
With a forced cast, compiler is ok but I don't think it's a good idea to brute-force it this way. How do I fix this?
You are NOT following the official documentation when declaring your thread functions.
Your original declarations were using
int
as the return value, and__cdecl
(implicitly) as the calling convention. When you changed the return value toDWORD
, you did not change the calling convention.However, the documentation clearly shows the correct declaration:
DWORD
is anunsigned long
, andWINAPI
is a macro that maps to the__stdcall
calling convention (see Windows Data Types).So, the correct declaration of your functions would be:
However, since
CreateThread()
takes anLPTHREAD_START_ROUTINE
as input, which is declared asDWORD (WINAPI*)(LPVOID)
(see the actual declaration inwinbase.h
), you should declare your functions to match: