无法将'void* (Network::*)(void*)'转换为'void* (*)(void*)'

4
我是一名初学者C++程序员,正在Linux机器上编程。
我遇到了这个错误:
cannot convert ‘void* (Network::*)(void*)’ to ‘void* (*)(void*)’ for argument ‘3’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)

这句话的意思是:它来自于这一行:

pthread_create(&thread_id,0,&Network::SocketHandler, (void*)csock );

我要调用的函数是:

void* Network::SocketHandler(void* lp)

我在头文件中将这两个函数声明为私有。

你们有没有看出我的错误?

2个回答

6
您正在使用成员函数指针,而需要的是普通函数指针。成员函数有一个隐含的额外参数:this。pthread_create没有考虑到这一点。
您需要将函数设置为static才能在pthread_create中使用它。然后可以使用void*参数来传递本应该是this指针的内容。
个人建议,最好放弃pthreads,转而使用C++11的std::thread,如果没有C++11实现,则可以使用boost::thread。

哦,你可能是对的,他可能不打算与“网络”一起使用它。+1 - Seth Carnegie
使用 pthread_create() 的最后一个参数将 this 指针传递给该 static 方法。可以将 csock 值存储为 Network 类的成员,并通过 this 指针访问该值,或者将两个值存储在动态分配的 struct 中,该 static 方法在使用完毕后释放它。 - Remy Lebeau
C++11?它比pthreads更容易/更好吗?在哪里可以找到关于C++11线程的信息?谢谢。 - mschuurmans
2
@user1971401 是的,它好得多了,只需在谷歌上搜索C++11的std::thread即可。 - Seth Carnegie
@SethCarnegie的“more bettter”=棒极了(喜欢那个词组)。 - WhozCraig
@SethCarnegie 你几乎必须这样做。我对这场混乱的贡献:在此处了解更多关于C++11线程的信息。 - WhozCraig

2
编辑:如果您不想在函数中使用Network实例,则K-ballo的答案是您需要的。如果您使用,则请继续阅读。 pthread_create预期调用普通函数,而您正在尝试将成员函数用作非成员函数。成员函数不是普通函数,因为它必须具有调用对象。
您可以创建一个函数,在其上调用NetworkSocketHandler,然后以这种方式执行操作:
void* call_sockethandler(void* nw) {
    Network* network = static_cast<Network*>(nw);

    void* result = network->SocketHandler(somearg);

    // do something w/ result

    return nullptr;
}

Network nw; // this can't go out of scope though
pthread_create(&thread_id, 0, call_sockethandler, &nw); 

为什么要使用reinterpret_cast而不是static_cast - K-ballo
@K-ballo 因为我太蠢了。 - Seth Carnegie
我之所以问是因为有合法的理由在指针之间使用 reinterpret_cast,但我似乎总是记不住它们。 - K-ballo
根据https://dev59.com/z3VC5IYBdhLWcg3wZwFT,@K-ballo表示`reinterpret_cast`无法用于从`void*`进行转换,因为它不是对象类型。我认为`reinterpret_cast`适用于除了沿继承层次结构进行转换、去除const属性、在可转换类型之间进行转换以及从`void*`进行转换之外的所有情况,但请不要引用我的话。 - Seth Carnegie
很奇怪,在某些情况下,reinterpret_cast 会导致从 void* 进行两次 static_cast,我原本以为从 void* 进行 reinterpret_cast 应该是有效的...幸运的是,我永远不必使用这些低级工具! - K-ballo
2
+1,好答案。如果OP对于在类中隐藏实际线程创建感到好奇,一个基本的示例如下:链接。请注意,链接的示例仅涉及设置包装器;同步、加入等操作都留待完成,但是处理程序设置应该是明显的,这也是问题的目标。 - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接