2009-11-29 4 views
1

C++ 사용.새로운 스레드입니다.이 컴파일 오류는 무엇을 의미합니까?

pthread_t threads[STORAGE]; // 0-99 

... 

void run() 

Error>>> int status = pthread_create(&threads[0], NULL, updateMessages, (void *) NULL); 
if (status != 0) 
{ 
    printf("pthread_create returned error code %d\n", status); 
    exit(-1); 
} 

...

void ClientHandler::updateMessages(void *) 
{ 
    string reqUpdate = "91"; // Request for update 
    string recvMSG; 
    while (true) 
    { 
     sleep(5); 
     sending(sock,reqUpdate); // send 
     recvMSG = receiving(sock); // receive 
     QString output(recvMSG); 
     emit signal_chat(output, 0); // Print message to text box 
    } 
} 

...

컴파일 오류 : 무슨 잘못 TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’

나는 알아낼 수 없습니다. 미리 감사드립니다.

답변

7

멤버 함수에 대한 포인터가 작동하는 추가 개체를 필요로하기 때문에 멤버 함수에 대한 포인터가 동일한 시그니처가있는 전역 함수와 다릅니다. 따라서이 두 유형의 함수에 대한 포인터는 호환되지 않습니다.

이 경우 멤버 함수 포인터를 pthread_create에 전달할 수는 있지만 멤버가 아닌 (또는 정적 인) 함수에 대한 포인터는 전달할 수 없다는 것을 의미합니다. 이 문제에 대한 주위에 작업 한 후 전달 된 객체의 메소드를 호출 전역 함수에 객체에 대한 포인터를 전달하는 pthread_create의 등의 매개 변수를 사용하는 것입니다 :는 pthread_create로

class ClientHandler { 
public: 
    void updateMessages(); 
    void run(); 
}; 

// Global function that will be the threads main function. 
// It expects a pointer to a ClientHandler object. 
extern "C" 
void *CH_updateMessages(void *ch) { 
    // Call "real" main function 
    reinterpret_cast<ClientHandler*>(ch)->updateMessages(); 
    return 0; 
} 

void ClientHandler::run() { 
    // Start thread and pass pointer to the current object 
    int status = pthread_create(&threads[0], NULL, CH_updateMessages, (void*)this); 
    ... 
} 
+0

대단히 감사합니다 ^^ –

6

스레드와 관련이 없으며, 일반적인 C++ 오류입니다. 호환되지 않는 유형의 함수 포인터를 전달 중입니다.

함수 포인터가 서명이 같더라도 함수 포인터는 멤버 인스턴스 함수 포인터와 같지 않습니다. * 통과 된 암시 적 참조가 있기 때문입니다. 너는 이것을 피할 수 없다.

+0

그래서 개체 내에서 스레드를 만들 수 없습니다 :

귀하의 코드는이 같은 무언가로 다시 쓸 수 있을까? –

+0

updateMessage를 클래스의 정적 함수로 변경할 수 있습니다. 그런 다음 멤버 데이터에 액세스하려면 "this"포인터를 컨텍스트 변수로 pthread_create에 전달하면 updateMessages 함수의 첫 번째 매개 변수로 전달됩니다. – rossoft

+0

@rossoft 예, 작동합니다. – MarkR

0

은 무료 기능을한다, 생성 콜백 무료 기능

+1

static 멤버 함수의 ABI는 컴파일러 정의이므로 호출 규칙을 보장 할 수 없기 때문에 기술적으로 허용되지 않습니다. __If__ 이것이 당신의 플랫폼 컴파일러에서 작동한다면 당신은 단지 운이 좋을 것입니다. pthread (C 라이브러리이기 때문에)에서 함수 포인터가 "C"ABI를 사용할 것으로 기대하고 있습니다. 따라서 함수는 올바른 호출 규칙이 사용되도록하기 위해 C++ 코드의 extern "C"로 표시되어야합니다. –

+0

감사하지만 게시물을 삭제할 수 없습니다. – yesraaj

-1

당신은 대신, 일반, 세계 하나의 멤버 함수를 통과하고 있기 때문에 작동 ClientHandler에

static void Callback(void * this_pointer,int other_arg) { 
    ClientHandler* self = static_cast< ClientHandler*>(this_pointer); 
    self-> updateMessages(other_arg); 
} 
and call pthread_create as follows 

pthread_create(&threads[0], NULL, &ClientHandler::Callback, (void *) pointer_to_ClientHandler,int other_arg); 

내부의 정적 기능 (무료 기능입니다).

그냥 정의

void updateMessages(void *) { 
static ClientHandler c; 
// use c.. 
} 
0

YoLinux 좋은 pthread와 자습서를 가지고 그 스레드에 대한 학습에 내 도움을.

0

다른 사람들이 이미 말했듯이, 문제는 기능 간의 서명이 다르다는 것입니다. 클래스 멤버 함수에는 항상 "비밀"추가 매개 변수 인 포인터가 있습니다. 따라서 전역 함수가 필요한 멤버 함수는 결코 전달할 수 없습니다. Boost.Bind와 같은 라이브러리를 사용하거나 함수를 클래스의 정적 멤버로 만들면이 문제를 해킹 할 수 있습니다.

하지만 가장 간단한 해결책은 다른 스레딩 API를 사용하는 것입니다.

Boost.Thread는 C++ 용 아주 멋진 스레딩 라이브러리입니다 (pthreads는 C 용으로 설계되었으므로 클래스 메소드와 같은 C++ 기능으로는 잘 돌아 가지 않습니다).

사용하는 것이 좋습니다.

class ClientHandler { 
public: 
    ClientHandler(/* All the parameters you want to pass to the thread. Unlike pthreads you have complete type safety and can pass as many parameters to this constructor as you like */){...} 
    void operator()() // boost.thread calls operator() to run the thread, with no parameters. (Since all parameters were passed in the constructor and saved as member variables 
    { 
    string reqUpdate = "91"; // Request for update 
    string recvMSG; 
    while (true) 
    { 
     sleep(5); 
     sending(sock,reqUpdate); // send 
     recvMSG = receiving(sock); // receive 
     QString output(recvMSG); 
     emit signal_chat(output, 0); // Print message to text box 
    } 
    } 
    // whatever arguments you want to pass to the thread can be stored here as member variables 
}; 


boost::threead_group gr; // can store all your threads here, rather than being limited to your fixed-size array 

gr.create_thread(ClientHandler(/* construct a ClientHandler object with the parameters you like*/)); 
관련 문제