CreateThread中的转换错误

时间:2017-09-27 23:50:38

标签: c visual-studio winapi

当我尝试使用CreateThread函数时,我有一个奇怪的错误。这是我的代码:

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_threadreceiver_threadserverconn_thread是这样定义的函数:

int serverconn_thread(LPVOID args);

Visual Studio编译器给出了这个错误:

Error   C2440   'function': cannot convert from 'int (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'

我真的不明白,因为我认为我已经完成what the official documentation suggests

不,将线程函数的返回类型更改为DWORD并没有解决任何问题,错误只会更改为:

Error   C2440   'function': cannot convert from 'DWORD (__cdecl *)(LPVOID)' to 'LPTHREAD_START_ROUTINE'

奇怪的是,如果我这样改变它:

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)
    )

使用强制转换,编译器可以,但我不认为以这种方式强制执行它是个好主意。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

在声明线程功能时,您没有关注official documentation

您的原始声明使用int作为返回值,__cdecl(隐式)作为调用约定。当您将返回值更改为DWORD时,您没有更改调用约定。

但是,documentation清楚地显示了正确的声明:

DWORD WINAPI ThreadProc(
  _In_ LPVOID lpParameter
);

DWORDunsigned longWINAPI是一个映射到__stdcall调用约定的宏(请参阅Windows Data Types)。

因此,您的函数的正确声明将是:

unsigned long __stdcall printer_thread(void *args);
unsigned long __stdcall receiver_thread(void *args);
unsigned long __stdcall serverconn_thread(void *args);

但是,由于CreateThread()LPTHREAD_START_ROUTINE作为输入,声明为DWORD (WINAPI*)(LPVOID)(请参阅winbase.h中的实际声明),因此您应声明要匹配的函数:

DWORD WINAPI printer_thread(LPVOID args);
DWORD WINAPI receiver_thread(LPVOID args);
DWORD WINAPI serverconn_thread(LPVOID args);