2012-08-17 20 views
5

Estoy tratando de crear un nuevo hilo con una clase "CameraManager" pero tengo el siguiente error:no se puede convertir '* void (MyClass :: *) (void *) en void * (*) (void *) en la función pthread_create

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

i definido en el archivo cameramanager.h:

public: 
void *dequeueLoop(void *ptr); 

y en el 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(); 
} 

no quiero a declar e dequeueLoop como función estática también intenté declarar dequeueLoop como una función de amigo de clase de la siguiente manera, pero luego no tiene alcance en las variables de clase 'highSpeedCamera' y 'dequeuing' y el compilador también me dice que 'dequeueLoop' era no declarado en este ámbito

para hacer una función dequeueLoop amigo que hice:

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(); 
    } 
} 

¿Dónde estoy haciendo mal?

+1

¿Por qué no quieres que sea una función de miembro estático? Siempre puede pasar 'this' como argumento para que tenga acceso a sus datos de miembros privados. – pstrjds

Respuesta

6

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

Si desea utilizar pthreads, entonces necesitará una función estática o no miembro para el punto de entrada. Puede pasar un puntero al objeto de esta función, usándolo como un trampolín a la función miembro no estática:

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 

Alternativamente, si usted tiene un compilador moderno, se puede usar la biblioteca de rosca estándar en su lugar:

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

Si no tiene el compilador moderno, puede considerar boost :: thread - será la misma sintaxis agradable – nogard

+0

gracias, probé la primera implementación que me sugirió, pero cuando compilo tengo el siguiente error: 'En funcionamiento 'void * dequeEntry (void *)' 'valor nulo no ignorado, ya que debe ser' –

+0

@GabrieleGambotto: Eso suena como que 'dequeueLoop' no está declarado para devolver nada, a diferencia de la pregunta que está declarada para devuelve 'void *', pero se olvida de devolver algo. O consigue 'dequeueLoop' para devolver el valor de retorno del hilo, o coloca una declaración' return' por separado en 'dequeueEntry'. –

2

No se puede usar un puntero a la función de miembro como un puntero a menos que sea estático. Tendrás que hacer que dequeueLoop sea una función gratuita, o escribir una función gratuita como envoltorio para ella.

Para acceder a los miembros de la clase en una función libre, debe hacer que la función pase su puntero this como argumento final de pthread_create. Luego, haga que la función gratuita emita su argumento a un puntero a la clase.

3

Si desea que la función sea un miembro de la clase, debe ser static. Se debe a que se llamará directamente a la función de subproceso y no tendrá un puntero this válido. Esto puede ser resuelto por tener una función de contenedor, que se pasa el objeto real y luego llama a la función miembro adecuado:

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

Sin embargo, le recomiendo que empiece a utilizar la threading support en la nueva biblioteca estándar:

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