2014-02-12 140 views
1

我在做一個發送短信程序,但是當我在線程中創建與服務器的連接時,我得到一個錯誤。在C++中創建線程時出錯

g++ -L/usr/lib/i386-linux-gnu -o main Socket.cpp ServerSocket.cpp modemSMS_w.cpp main.cpp Config.cpp -lpthread -lserial -lxml2 -lmysqlclient 
modemSMS_w.cpp: In member function ‘void modem::enviasms()’: 
modemSMS_w.cpp:96:77: error: cannot convert ‘void* (modem::*)(void*)’ to ‘void* (*)(void*)’ for argument ‘3’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’ 

程序:

#include "modemSMS_w.hpp" 
#define CTRL_C "\x1A" 

using namespace LibSerial; 
using namespace std; 

modem::modem() 
{ 
} 

void *modem::func_servidor(void *ptr) 
{ 

ServerSocket server(30001); 

     try { 
       ServerSocket new_sock; 
       while(1) 
       { 
         server.accept(new_sock); 
         cout << "Conexao aceita" << endl; 
       } 
     } 
     catch (SocketException& e) { 
       cout << "Erro: Criando Servidor" << endl; 
     } 

} 

int modem::setSerial() { 
..... 
.... 
... 
} 

void modem::enviasms(){ 

    pthread_t thread_servidor; 
    pthread_cond_t cv; 

    const int PORT_MON = 30000; 
    string serialPort = "/dev/ttyS0"; 

    int argc; 
    int ret; 
    char **argv; 

    cout << "\n------------------------\n MODEM GPRS \n------------------------" << endl; 
    string mensagem ="Conversao"; 
    mensagem.c_str(); 

    ret = pthread_cond_init(&cv, NULL); 
    bool envia = true; 
    envia = true; 
    if (ret != 0) 
    { 
      cout << "Erro na criação do evento. Por favor reeinicie o programa." << endl; 
    } 

    //ERROR IN THIS LINE 
    pthread_create(&thread_servidor, NULL,&modem::func_servidor, (void*) true); 

    Config config; 
    SerialStream ssStream; 
    setSerial(); 

.... 
... 
} 

對不起,不知道幾乎沒有在C++中創建線程已經試圖解決這個問題,但是沒有sucess。

+2

不知道你爲什麼要使用pthread_create原語來實現這樣的基本用法,但是如果你使用的是現代C++編譯器,最好使用'std :: thread'(或'boost:thread')。另外,對於你的問題,你傳遞一個指向一個成員函數的指針,指向一個自由函數的指針。那些不一樣。 – ereOn

+0

[如何從成員函數中獲取「簡單」函數指針]的可能重複(http://stackoverflow.com/questions/15958553/how-to-get-a-simple-function-pointer-from-a-成員函數) –

回答

1

您可以添加靜態函數的類,並在在pthread_create函數中使用它:

class modem { 
    public: 
     //... 
     static void* thread_func(void* arg); 
     //... 
}; 

void* modem::thread_func(void* arg) { 
    return reinterpret_cast<modem*>(arg)->func_servidor(); 
} 

void *modem::func_servidor() { 
    // some code 
} 

void modem::enviasms(){ 
    //some code scipped 
    if(pthread_create(&thread_servidor, NULL, &modem::thread_func, reinterpret_cast<void*>(this)) != 0) { 
     //some error handling code 
    } 
    //... 
    if(pthread_join(thread_servidor, NULL) != 0) { 
    // handle error 
    } 
} 

但是,恕我直言,這是更好的使用升壓或std線程。你不需要靜態函數使用這種方法:

auto thr = std::thread{ &modem::func_servidor, this }; 
//... 
thr.join(); 

但請注意,你必須檢查的對象,當你線程的存在是爲了將存在this點。

+0

我會試試這個 – Neto

+0

@Neto要小心 - 線程存在時'this'指針必須有效。如果調制解調器對象被銷燬並且線程仍然存在,您將會遇到未定義的行爲。 –

+0

它工作得很好......我不得不做一些改變,但是你幫了我很多人...... thx! – Neto

1

你永遠不會創建你的Modem類的實例,那麼如何調用該類的成員函數呢?

會員功能需要會員才能操作。不要將指針指向成員函數pthread_create。創建一個調用成員函數的非成員函數,並將指向它的指針傳遞給pthread_create

+0

即時通訊從C到C++,所以我不知道幾乎沒有關於類...我怎樣才能創建這個非成員函數並傳遞一個指針,該pthread_create? – Neto

+1

@Neto我會強烈要求你忘記線程,直到你理解了C++的基礎知識。當你試圖一次完成所有這些問題時,你永遠不會將這些問題排除在外。如果「你不能調用一個沒有類成員的非靜態類成員函數」對你來說並不明顯,或者你不知道這個「this」指針是什麼,那麼你就沒有業務與線程和類混淆了同一時間。 –

+0

是的,我已經在學習了,但我沒有太多的耐心。爲我的無知服務 – Neto