2011-06-15 46 views
0

我創建了一個widget.h文件,其中包含pthread_function的聲明,我想在widget.cpp中的該類Widget的成員函數destroyWidget中調用它。但總是顯示錯誤。我將顯示.cpp和.h文件。在成員函數內調用pthread_create?

widget.h文件


class Widget 
{ 
public: 
Widget(); 
void createWidget(int x,int y,int w,int h); 
void showWidget(); 
int wid; 
pthread_t thread; 
int *incomingval,id; 
void join(); 
Window win; 
XEvent evt; 
private: 
void* destroyWidget(void* ptr); 
Display *disp; 
int screenNumber; 
unsigned long white; 
unsigned long black; 
long eventMask; 
GC gc; 
int tbit; 
int *incoming,val; 
}; 

現在widget.cpp


Widget::Widget() 
{ 
disp=XOpenDisplay(NULL); 
screenNumber=DefaultScreen(disp); 
white=WhitePixel(disp,screenNumber); 
black=BlackPixel(disp,screenNumber); 
eventMask=StructureNotifyMask; 
tbit=0; 
} 

void Widget::createWidget(int x,int y,int w,int h) 
{ 
wid=w; 
win= XCreateSimpleWindow(disp,DefaultRootWindow(disp),x,y,w,h,1,white,black); 
} 

void Widget::showWidget() 
{ 
XMapWindow(disp,win); 
XFlush(disp); 
gc=XCreateGC(disp,win,0,NULL); 
XSetForeground(disp,gc,white); 
XDrawLine(disp,win,gc,wid-10,0,wid,10); 
XDrawLine(disp,win,gc,wid-10,10,wid,0); 
//calling the thread function 
pthread_create(&thread, NULL, destroyWidget, this); 
} 

void Widget::join() 
{ 
pthread_join(thread, NULL); 
} 
void* Widget::destroyWidget(void* ptr) 
{ 
Widget* mw = static_cast(ptr); 
eventMask=ButtonPressMask|ButtonReleaseMask; 
XSelectInput(disp,win,eventMask); 
do{ 
printf("id= %d",id); 
XNextEvent(disp,&evt); 
}while(evt.type!=ButtonRelease); 
XDestroyWindow(disp,win); 
XCloseDisplay(disp); 
return NULL; 
} 

現在的main.cpp文件



#include "widget.h" 
#include 
int main() 
{ 
Widget* w=new Widget(); 
Widget* n=new Widget(); 
n->createWidget(20,20,150,150); 
w->createWidget(50,50,250,250); 
n->showWidget(); 
w->showWidget(); 
n->join(); 
w->join(); 
return 0; 
} 

誤差

widget.cpp: In member function ‘void Widget::showWidget()’: 
widget.cpp:44:51: error: argument of type ‘void* (Widget::)(void*)’ does not match ‘void* (*)(void*)’ 
+1

Indendation確實做了很多事情來使你的代碼可讀。我強烈建議將來使用它。即使只有幾個空間也會變冷。 – 2011-06-15 13:58:13

+0

你應該**不**使用成員函數**甚至不是**一個靜態的。在這裏閱讀正確的解決方案。 HTTP://計算器。com/questions/6352280/pthread-create-error-in -c/6352434#6352434 – 2011-06-15 14:59:45

回答

6

問題是pthread_create是C風格的函數;你需要給它一個指向函數的指針。 Widget::destroyWidget()是指向成員功能。 (請注意,非靜態成員函數始終有一個隱含的this參數,它pthread_create不知道如何提供。)

看到這個問題的答案對一些可能的解決方案:pthread function from a class

+0

我嘗試過使用靜態,但是在整個函數中使用的變量出現錯誤 – HariHaraSudhan 2011-06-15 14:02:54

+1

@user:您是否嘗試了其他想法?即添加一個「靜態」輔助函數,然後調用成員函數? – 2011-06-15 14:06:59

+0

@Oli:不,如果可以的話,幫我一把。 – HariHaraSudhan 2011-06-15 14:08:26

0

就像奧利說的,當C風格的函數需要一個「正常」函數指針時,你不能使用成員函數。然而,你可以做的是做一個獨立的函數來調用你的destroyWidget()方法。

像這樣:

void* start_routine(void* arg) 
{ 
    Widget* widget = static_cast<Widget* >(arg); 

    widget->destroyWidget(); 

    return NULL; 
} 

void Widget::showWidget() 
{ 
    pthread_create(&thread, NULL, &start_routine, this); 
} 

void Widget::destroyWidget() 
{ 
    // your code 
} 
+0

nope dint wrk :( – HariHaraSudhan 2011-06-15 14:17:21

+0

對不起!在start_routine中有一個錯字現在已經修復了。 – 2011-06-15 14:23:01

+0

widget.cpp:在成員函數'void Widget :: showWidget()'中: widget.cpp:34:33:error:ISO C++禁止使用非限定或加括號的非靜態成員函數的地址來形成指向成員函數的指針。說'&Widget :: start_routine' widget.cpp:34:52:error:can not convert'void *(Widget :: * (*)(void *),void *)' – HariHaraSudhan 2011-06-15 14:25:09

0

的第三個參數pthread_create具有(在C++)簽名:

extern "C" void* (*pointerToFunction)(void*); 

你試圖通過它的成員函數的地址:

void* (Widget::*pointerToMemberFunction)(void*); 

簽名是不兼容的:第二個需要一個對象 來叫它,而不是extern "C"

處理此問題的最簡單方法是使用boost::thread,其中所有 都是功能對象支持。否則,你可以定義一些 類似如下:

struct AbstractTask 
{ 
    virtual ~AbstractTask() {} 
    virtual void* run() = 0; 
}; 

template<typename T, void* (T::*ptr)()> 
class Task 
{ 
    T* myObject; 
public: 
    Task(T* object) : myObject(object) {} 
    virtual void* run() 
    { 
     return (myObject->*ptr)(); 
    } 
}; 

extern "C" void* taskRunner(void* arg) 
{ 
    std::auto_ptr<AbstractTask> p(static_cast<AbstractTask*>(arg)); 
    return p->run(); 
} 

pthread_t taskStarter(AbstractTask* obj) 
{ 
    pthread_t result; 
    pthread_create(&result, NULL, &taskRunner, obj); 
    return result; 
} 

啓動一個線程,你再撥打:

(這是從內存中,從早期的一個項目,所以可能會有一些 錯別字,但你明白了,而且你可能想在taskStarter中添加一些 錯誤處理。)

+0

不能理解這個程序,你能否參考我的程序來解釋它。我非常需要它。 – HariHaraSudhan 2011-06-15 14:23:16

+0

@ user796094這個想法是,你傳遞給'pthread_create'的是指向一個函數的指針,該函數將其參數轉換爲指向接口的指針,並調用其中的函數。然後你從界面派生出來做你想做的任何事情;在這種情況下,爲了使事情更簡單,有一個模板來創建派生類,所以你不必每次寫它。傳遞給'pthread_create'的實際函數會破壞你創建的對象;因爲涉及多態性,並且生命週期不遵循範圍,所以你「新」。 – 2011-06-15 18:07:49