2012-07-17 70 views
1

可能重复:
pthread Function from a ClassC++并行线程成员函数

我有这样的代码,我不能因为pthread_create行编译:

void* gtk_functor::_threaded_run(void* win) 
{ 
    Gtk::Window* w = static_cast<Gtk::Window*>(win); 
    Gtk::Main::run(*w); 
    delete w; 
} 

void gtk_functor::operator()(Gtk::Window& win, bool threaded) 
{ 
    if (threaded) 
    { 
     pthread_t t_num; 
     pthread_create(&t_num, NULL, (void* (*)(void*))&gtk_functor::_threaded_run, static_cast<void*>(&win)); 
    } 
    else 
    { 
     Gtk::Main::run(win); 
    } 
} 

这海湾合作委员会行:

g++ -o main 'pkg-config --cflags --libs sqlite3 gtkmm-3.0' -lpthread main.cpp

做到底编译输出:

code/ui.cpp: In member function 'void ui::gtk_functor::operator()(Gtk::Window&, bool)': 
code/ui.cpp:45:65: warning: converting from 'void* (ui::gtk_functor::*)(void*)' to 'void* (*)(void*)' [-Wpmf-conversions] 

,显然该代码不能正常工作,我得到sementation faultif (threaded)提高。

我知道它与演员,但我不知道传递成员函数到pthread_create的正确形式。有什么建议么?

+1

摆脱铸造,使'_threaded_run'静态的。 – ildjarn 2012-07-17 18:35:48

+1

'gtk_functor :: _ threaded_run'不是一个函数。这是一个*成员函数*。要求能够“呼叫”裸体成员功能是没有意义的。必须有一个**对象**,它的成员函数被调用。 – 2012-07-17 18:35:54

+3

另请参阅http://stackoverflow.com/q/1151582/1025391 – moooeeeep 2012-07-17 19:07:14

回答

5

尝试使_threaded_run静态。在标题:

private: 
    static void* _threaded_run(void*); 

并在实施:

void* gtk_functor::_threaded_run(void* win) { 
    Gtk::Window* w = static_cast<Gtk::Window*>(win); 
    Gtk::Main::run(*w); 
    delete w; 
} 

然后创建线程时:

pthread_create(&t_num, NULL, &gtk_functor::_threaded_run, static_cast<void*>(&win)); 
+0

谢谢,它确实有效,只需用'gtk_functor :: _ threaded_run'代替'gtk_functor._threaded_run'。我一直在寻找这个,尽管我仍然坚持我对Kerrek SB的回答的评论,因为我们正在做C++。标准至关重要,我认为也影响着我们的心态。 – Haix64 2012-07-17 18:55:02

+4

pthreads是一个'C库'。因此它只理解'C'指向函数。传递一个指向静态方法的指针是容易出错的。您只应该将其声明为'extern“C”'的函数的地址,或者仅由C编译器而不是C++编译器编译。标准中没有任何东西保证C++函数或静态方法与C函数具有相同的调用约定。 – 2012-07-17 19:27:02

+0

@LokiAstari:Doh!那就对了。我可以用'extern“C”'声明一个静态方法吗? – Linuxios 2012-07-17 19:39:57

5

由于@ildjarn建议,只是做一个免费的功能:

void * threaded_run(void * win) 
{ 
    Gtk::Window * const w = static_cast<Gtk::Window*>(win); 
    Gtk::Main::run(*w); 
    delete w; 
} 

// ... 

pthread_create(&t_num, NULL, threaded_run, &win); 

由于功能不依赖于任何特定gtk_functor对象的状态,存在使其成为一个成员函数是没有意义的。


在假设不同的世界里,你真的希望对象的成员函数在一个单独的线程调用,需要传递的对象的对象引用周围不知何故,通常通过参数空指针:

struct Foo 
{ 
    void * run() { /* ... use state ... */ } 

    /* ... state ... */ 
}; 

Foo x; 
pthread_t pt; 

// start a new execution context with x.run(): 
pthread_create(&pt, NULL, FooInvoker, &x); 

extern "C" void * FooInvoker(void * p) 
{ 
    return static_cast<Foo*>(p)->run(); 
} 

事实上,你甚至可能希望更多的上下文信息打包成一些辅助结构和一个空指针传递给到线程调用函数。

+1

不应该有自由函数周围的匿名命名空间吗? – moooeeeep 2012-07-17 18:47:09

+0

您的第一个解决方案确实有效。我认为_threaded_run然后是gtk_functor的助手。尽管我发现它可以工作,但我并没有尝试第二种解决方案,但我认为不要依赖这些技巧,只要'std :: thread'在GCC中完全实现,就可以暂时保留我们的代码并升级。 ? (虽然谢谢) – Haix64 2012-07-17 18:49:13

+0

@ ai64:尽管!std :: thread并不能帮助你理解关于对象和成员函数的基本概念误解。 – 2012-07-17 18:53:17