2012-08-17 16 views
5

Ich versuche, einen neuen Thread mit einer Klasse "CameraManager" zu erstellen, aber ich habe die folgende Fehlermeldung:kann '* void (MyClass :: *) (void *) in void * (*) (void *) in der Funktion pthread_create nicht konvertieren

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

i definiert in der cameramanager.h Datei:

public: 
void *dequeueLoop(void *ptr); 

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

ich will nicht declar e dequeueLoop als statische Funktion Ich habe auch versucht, dequeueLoop als Klassenfreund-Funktion auf die folgende Weise zu deklarieren, aber dann hat es keinen Spielraum für Klassenvariablen 'highSpeedCamera' und 'dequeuing' und der Compiler sagt mir auch, dass 'dequeueLoop' war nicht in diesem Bereich erklärt

einen Freund Funktion zu machen dequeueLoop ich tat:

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

Wo mache ich falsch?

+1

Warum möchten Sie es nicht zu einer statischen Elementfunktion machen. Sie können 'this' immer als Argument übergeben, um Zugriff auf Ihre privaten Mitgliedsdaten zu erhalten. – pstrjds

Antwort

6

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

Wenn Sie Pthreads verwenden möchten, benötigen Sie eine statische oder nicht-Member-Funktion für den Einstiegspunkt. Sie können einen Zeiger auf das Objekt auf diese Funktion übergeben, es als Trampolin in die nicht-statische Member-Funktion:

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 

Alternativ, wenn Sie einen modernen Compiler haben, können Sie die Standard-Thread-Bibliothek stattdessen verwenden:

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

Wenn Sie nicht moderne Compiler haben, können Sie boost :: thread betrachten - es wird die gleiche nette Syntax sein – nogard

+0

danke, ich habe versucht, die erste Implementierung, die Sie mir vorgeschlagen, aber wenn ich kompiliere habe ich den folgenden Fehler: 'In Funktion 'void * dequeEntry (void *)' 'void value nicht ignoriert, wie es sein sollte' –

+0

@GabrieleGambotto: Das hört sich so an, als würde dein 'dequeueLoop' nichts zurückgeben, im Gegensatz zu dem, in dem deine Frage steht return 'void *', vergisst aber, etwas zurückzugeben. Entweder "dequeueLoop" holen, um den Rückgabewert des Threads zurückzugeben, oder eine separate "return" -Anweisung in "dequeueEntry" setzen. –

2

Sie können einen Zeiger auf Elementfunktion nicht als Funktionszeiger verwenden, es sei denn, es ist statisch. Sie müssen eine freie Funktion dequeueLoop machen oder eine freie Funktion als Wrapper dafür schreiben.

Um auf die Klassenmitglieder in einer freien Funktion zuzugreifen, sollten Sie die Funktion this Zeiger als das letzte Argument von Pthread_create übergeben. Dann muss die free-Funktion ihr Argument auf einen Zeiger auf die Klasse anwenden.

3

Wenn die Funktion ein Mitglied der Klasse sein soll, muss static sein. Das liegt daran, dass die Thread-Funktion direkt aufgerufen wird und keinen gültigen Zeiger this hat. Dies kann durch die mit einer Wrapper-Funktion gelöst werden, dass die tatsächliche Objekt übergeben wird, und ruft dann die richtige Elementfunktion:

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

Allerdings würde ich empfehlen Sie beginnen, die threading support in der neuen Standard-Bibliothek:

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