在成员函数内调用 pthread_create ?

发布于 2024-11-15 16:44:01 字数 2078 浏览 1 评论 0原文

我创建了一个包含 pthread_function 声明的 widget.h 文件,我想在 widget.cpp 中该 Widget 类的成员函数 destroyWidget 中调用它。但总是显示错误。我将显示 .cpp 和 .h 文件。

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*)’

I created a widget.h file containing the declartions of pthread_function and I wanted to call it in a member function destroyWidget of that class Widget in widget.cpp. but always shows an error. I'll show the .cpp and .h file.

widget.h file


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

now the 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;
}

now the main.cpp file



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

the error is

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风柔一江水 2024-11-22 16:44:01

问题是 pthread_create 是一个 C 风格的函数;你需要给它一个函数指针。 Widget::destroyWidget() 是一个指向成员函数的指针。 (请记住,非静态成员函数始终具有隐含的 this 参数,而 pthread_create 不知道如何提供该参数。)

请参阅此问题的答案以获取一些可能的解决方案:类中的 pthread 函数

The problem is that pthread_create is a C-style function; you need to give it a pointer-to-function. Widget::destroyWidget() is a pointer-to-member-function. (Remember that non-static member functions always have an implied this argument, which pthread_create doesn't know how to provide.)

See the answers to this question for some possible solutions: pthread function from a class.

梦断已成空 2024-11-22 16:44:01

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

要启动一个线程,然后调用:(

thread = taskStarter( new Task<Widget, &Widget::destroyWidget>( this ) );

这是来自早期项目的记忆,因此可能有一些
虽然里面有错别字,但你明白了。你可能想添加一些
taskStarter 中的错误处理。)

The third argument to pthread_create has the signature (in C++):

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

You're trying to pass it the address of a member function:

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

The signatures are incompatible: the second requires an object on which
to call it, and is not extern "C".

The simplest way of handling this is to use boost::thread, with all
it's functional object support. Otherwise, you can define something
like the following:

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

To start a thread, you then call:

thread = taskStarter( new Task<Widget, &Widget::destroyWidget>( this ) );

(This is from memory, from an earlier project, so there might be some
typos in it, but you get the idea. And you probably want to add some
error handling in taskStarter.)

伴我心暖 2024-11-22 16:44:01

就像 Oli 所说,当 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
}

Like Oli said you can't use a member function when a C-style function expects a "normal" function pointer. However, what you can do is make a separate function that calls back your destroyWidget() method.

Like so:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文