不能在pthread_create函数中将void *(MyClass :: *)(void *)转换为void *(*)(void *)

问题描述:

我试图用类“CameraManager”创建一个新线程,但我有以下错误:不能在pthread_create函数中将void *(MyClass :: *)(void *)转换为void *(*)(void *)

cannot convert '*void(CameraManager:: *)(void*) to void*(*)(void*) in pthread_create function

我在cameramanager.h文件中定义:

public: 
void *dequeueLoop(void *ptr); 

,并在cameramanager.cpp

void CameraManager::startDequeuing(){ 
dequeuing = true; 
dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL); 
} 

void *CameraManager::dequeueLoop(void *ptr){ 
while(dequeuing){ 
    highSpeedCamera->dequeue(); 
    highSpeedCamera->enqueue(); 
} 

我不想declar e dequeueLoop作为一个静态函数我也尝试以下面的方式声明dequeueLoop为一个类的朋友函数,但它没有范围在类变量的'highSpeedCamera'和'出队',编译器也告诉我'dequeueLoop'是在此范围内没有声明

使dequeueLoop友元函数我所做的:

cameramanager.h

public: 
friend void *dequeueLoop(void *ptr); 

cameramanager.cpp

void CameraManager::startDequeuing(){ 
    dequeuing = true; 
    dequeueThreadId = pthread_create(&dequeueThread, NULL, &CameraManager::dequeueLoop, NULL); 
} 
void *dequeueLoop(void *ptr){ 
    while(dequeuing){ 
     highSpeedCamera->dequeue(); 
     highSpeedCamera->enqueue(); 
    } 
} 

我在哪里做错了?

+1

为什么你不想让它成为一个静态成员函数。您始终可以将'this'作为参数传递给您,以便您可以访问您的私有成员数据。 – pstrjds 2012-08-17 12:50:54

I don't want to declare dequeueLoop as a static function

如果你想使用pthreads,那么你需要一个静态或非成员函数作为入口点。您可以将指针传递给你的对象到这个功能,使用它作为一个蹦床进入非静态成员函数:

static void * dequeueEntry(void * self) { 
    return static_cast<CameraManager*>(self)->dequeueLoop(); 
} 

dequeueThreadId = pthread_create(
    &dequeueThread, NULL, 
    &CameraManager::dequeueEntry, // <-- pointer to trampoline function 
    this);      // <-- pointer to object for member function 

或者,如果你有一个现代的编译器,你可以使用标准的线程库,而不是:

std::thread thread(&CameraManager::dequeLoop, this); 
+3

如果你没有现代编译器,你可以考虑boost :: thread - 它会是相同的很好的语法 – nogard 2012-08-17 13:06:21

+0

谢谢,我试过你建议我的第一个实现,但是当我编译时,我有以下错误: 'In function 'void * dequeEntry(void *)' 'void value不会被忽略,因为它应该是' – 2012-08-17 13:12:32

+0

@GabrieleGambotto:听起来你的'dequeueLoop'没有声明返回任何东西,不像你的问题中声明的那样返回'void *',但忘记返回任何东西。或者让'dequeueLoop'返回线程的返回值,或者在'dequeueEntry'中放置一个单独的'return'语句。 – 2012-08-17 13:29:50

除非是静态的,否则不能使用指向成员函数的指针作为函数指针。您必须使dequeueLoop成为一个免费函数,或者写一个免费函数作为它的包装。

访问类成员免费功能,您应该具备的功能它传递的this指针在pthread_create的最后一个参数。然后让*函数将其参数转换为指向该类的指针。

如果你想要的功能是类的成员,它必须static。这是因为线程函数将被直接调用,并且没有有效的指针this。这可以通过包装函数,获取传递实际的对象,然后调用适当的成员函数来解决:

void *dequeueLoopWrapper(void *p) 
{ 
    CameraManager *cameraManager = static_cast<CameraManager*>(p); 
    camereraManager->dequeueLoop(); 
    return nullptr; 
} 

// ... 

void CameraManager::startDequeuing() 
{ 
    dequeuing = true; 
    dequeueThreadId = pthread_create(&dequeueThread, NULL, dequeueLoopWrapper, this); 
} 

不过,我建议你开始在新的标准库使用threading support

void CameraManager::startDequeuing() 
{ 
    dequeuing = true; 
    myThread = std::thread(&CameraManager::dequeueLoop, this); 
}