WINAPI:在 class 成员函数上创建新线程 - 不兼容的参数类型
WINAPI: Create new thread on class member function - incompatable parameter type
我一直在将一些相当程序化的 C++ 重新设计成更 classy 的东西。原始代码运行得很好,其中一部分启动了一个新线程来进行一些文件清理。执行此清理的函数是新线程的入口点。请参阅下面的代码。注意:此代码不会执行,但它显示了工作原理。
#include <stdlib.h>
// Structure for passing application data to a new thread.
typedef struct threadData {
networkShare* netArchive;
rig* rigInfo;
rigDatabase* dbConn;
networkConn* netConn;
char* logBuffer;
} THREADDATA;
// Global handle to a mutex object
// Used to control access to the inter thread log buffer
HANDLE ghMutex;
DWORD WINAPI cleanLocalArchive(LPVOID lpParam) {
THREADDATA* p_threadData = (THREADDATA*)lpParam;
// ... Do stuff ...
return <<something>>;
}
int main(int argc, char** argv) {
// Variables for local archive thread
HANDLE h_CleanerThread = 0;
THREADDATA* p_threadData = NULL;
DWORD dwThreadId;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL) {
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
// Declare the data structure for passing app setting to a new Thread and populate it.
p_threadData = DBG_NEW THREADDATA;
p_threadData->netArchive = &rigArchive;
p_threadData->rigInfo = &thisRig;
p_threadData->logBuffer = (char*)malloc(BUF_SIZE);
p_threadData->dbConn = &archiveDB;
p_threadData->netConn = &netConnection;
// Initialise p_threadData->logBuffer in case we never put anything else in there.
sprintf_s(p_threadData->logBuffer, BUF_SIZE, "");
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
cleanLocalArchive, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// ... Do other stuff ...
return 0;
}
我现在已经将代码重构为 classes,函数 "cleanLocalArchive" 是应用程序 class AircatFeeder 的成员函数。当我在 CreateThread() 中调用此成员函数时,根据我对代码所做的操作,我会收到各种错误:
原样:调用行 = "cleanLocalArchive,"
error C3867: 'AirCatFeeder::cleanLocalArchive': non-standard syntax; use '&' to create a pointer to member
所以我添加了一个符号:call line = "&cleanLocalArchive,"
error C2276: '&': illegal operation on bound member function expression
error C2660: 'CreateThread': function does not take 5 arguments
经过一番摸索和 Google-Foo 我发现 this link 我希望它能解决问题。它当然阐明了原因。我在 class 之外创建了一个包装函数并尝试调用它。该函数及其调用如下:
函数调用:
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
trampoline, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
包装函数:
DWORD trampoline(LPVOID data) {
AirCatFeeder* scheduler = static_cast<AirCatFeeder*>(data);
return scheduler->cleanLocalArchive(data);
}
但是,我仍然收到相同的 issues/error 消息。无论我调用成员函数,还是包装函数,IntelliSense 仍然报类似的错误信息:
argument of type "DWORD(*)(LPVOID lpParam)" is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
希望现在我想要实现的目标已经很清楚了。有人可以教育我我做错了什么吗?谢谢。
Hans Passant 提供的回答。请参阅问题评论:
trampoline 的定义中缺少 WINAPI。
我一直在将一些相当程序化的 C++ 重新设计成更 classy 的东西。原始代码运行得很好,其中一部分启动了一个新线程来进行一些文件清理。执行此清理的函数是新线程的入口点。请参阅下面的代码。注意:此代码不会执行,但它显示了工作原理。
#include <stdlib.h>
// Structure for passing application data to a new thread.
typedef struct threadData {
networkShare* netArchive;
rig* rigInfo;
rigDatabase* dbConn;
networkConn* netConn;
char* logBuffer;
} THREADDATA;
// Global handle to a mutex object
// Used to control access to the inter thread log buffer
HANDLE ghMutex;
DWORD WINAPI cleanLocalArchive(LPVOID lpParam) {
THREADDATA* p_threadData = (THREADDATA*)lpParam;
// ... Do stuff ...
return <<something>>;
}
int main(int argc, char** argv) {
// Variables for local archive thread
HANDLE h_CleanerThread = 0;
THREADDATA* p_threadData = NULL;
DWORD dwThreadId;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL) {
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
// Declare the data structure for passing app setting to a new Thread and populate it.
p_threadData = DBG_NEW THREADDATA;
p_threadData->netArchive = &rigArchive;
p_threadData->rigInfo = &thisRig;
p_threadData->logBuffer = (char*)malloc(BUF_SIZE);
p_threadData->dbConn = &archiveDB;
p_threadData->netConn = &netConnection;
// Initialise p_threadData->logBuffer in case we never put anything else in there.
sprintf_s(p_threadData->logBuffer, BUF_SIZE, "");
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
cleanLocalArchive, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// ... Do other stuff ...
return 0;
}
我现在已经将代码重构为 classes,函数 "cleanLocalArchive" 是应用程序 class AircatFeeder 的成员函数。当我在 CreateThread() 中调用此成员函数时,根据我对代码所做的操作,我会收到各种错误:
原样:调用行 = "cleanLocalArchive,"
error C3867: 'AirCatFeeder::cleanLocalArchive': non-standard syntax; use '&' to create a pointer to member
所以我添加了一个符号:call line = "&cleanLocalArchive,"
error C2276: '&': illegal operation on bound member function expression
error C2660: 'CreateThread': function does not take 5 arguments
经过一番摸索和 Google-Foo 我发现 this link 我希望它能解决问题。它当然阐明了原因。我在 class 之外创建了一个包装函数并尝试调用它。该函数及其调用如下:
函数调用:
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
trampoline, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
包装函数:
DWORD trampoline(LPVOID data) {
AirCatFeeder* scheduler = static_cast<AirCatFeeder*>(data);
return scheduler->cleanLocalArchive(data);
}
但是,我仍然收到相同的 issues/error 消息。无论我调用成员函数,还是包装函数,IntelliSense 仍然报类似的错误信息:
argument of type "DWORD(*)(LPVOID lpParam)" is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
希望现在我想要实现的目标已经很清楚了。有人可以教育我我做错了什么吗?谢谢。
Hans Passant 提供的回答。请参阅问题评论:
trampoline 的定义中缺少 WINAPI。