错误
invalid conversion from 'void*' to 'void* (*)(void*)'的解决方式
今天遇到这么一段代码:
class CMosThread
{
public:
void* ThreadFunc(void * lpvParam)
{
return NULL;
}
private:
pthread_t m_tid;
void create_thread()
{
pthread_create(&m_tid, NULL,ThreadFunc, this);
}
}
编译报错:error: argument of type 'void* (mos::CMosThread::)(void*)' does not match 'void* (*)(void*)'
因为之前在用c语言的时候, 起线程这样起也没出现过什么问题, 所以, 我习惯性的把这一行代码
pthread_create(&m_tid, NULL,ThreadFunc, this);改成了 pthread_create(&m_tid, NULL,(void*)ThreadFunc, this);强转了一下第三个参数的类型, 谁知道把问题搞复杂化了, 因为接着报了一个下面这样的错误:
error: invalid use of member (did you forget the '&' ?)
这下把我难道了, 度娘了很多, 有的说没定义, 有的说参数使用错误, 等等等等, 不一而足. 而且这个报错离谱的地方是, 它没有指出具体是哪个参数出现了错误, 所以, 我进行了下面一系列的实验(分别把这一样代码改成下面这样):
1.
pthread_create(NULL, NULL,ThreadFunc, this); //把第一个参数传NULL进去, 依然报
error: invalid use of member (did you forget the '&' ?)
2. 然后又改成这样pthread_create(&m_tid, NULL,(void*)ThreadFunc, this); //仍然报错:error: invalid use of member (did you forget the '&' ?)
3. 然后更离谱的来了pthread_create(&m_tid, NULL,(void*)&ThreadFunc, this);//报错:error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&mos::CMosThread::ThreadFunc'
error: invalid conversion from 'void*' to 'void* (*)(void*)'
4. 小样还收拾不了你了, 再来pthread_create(&m_tid, NULL,(void*)*ThreadFunc, this);//error: invalid use of member (did you forget the '&' ?)
5. pthread_create(&m_tid, NULL,NULL, this); //编译通过了
虽然经过了这么多实验, 但这证明了一个问题, 说明肯定是第3个参数传的还是有问题.
继续查找原因:
找到了下面一个博客
void *thread1()
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0)
提示:invalid conversion from 'void* (*)()' to 'void* (*)(void*)'
=============
改成: void *thread1(void *)
void* (*)(void*): (*)表示这里需要一个函数指针, (void*)表示参数类型需要为void*
参考:
=================
void main_thread ( void *ptr )
{
char *message1 = "Thread 1";
char *message2 = "Thread 2";
pthread_t thread3, thread4;
int iret3, iret4;
iret3 = pthread_create(&thread3, NULL, (void *)&print_message_function, (void *) message1);
iret4 = pthread_create(&thread4, NULL, (void *)&print_message_function, (void *) message2);
}
void print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
以上这段代码在用g++编译是会有如下错误:
invalid conversion from `void*' to `void*(*)(void*)
我们注意在Posix定义建立线程函数的原型:
extern int pthread_create (pthread_t *__restrict __threadp,
__const pthread_attr_t *__restrict __attr,
void *(*__start_routine) (void *),
void *__restrict __arg) __THROW;
这个call中的第三个参数是载入一个函数,这个函数有一个参数可以传入,返回一个 通用指针。
我们再来看看原来函数中是怎样调用这一原型的,基本上就是类似一下的调用方式:
(void *)&main_thread
这个表达式的含义:取一个指向函数main_thread的指针,然后将其转换为一个通用指针。
这就是说显然上述两个事情并非同一个事情,故而正确的调用方式是
iret3 = pthread_create(&thread3, NULL, print_message_function, (void *) message1);
处理函数的定义如下:
void* print_message_function( void *ptr )
值得注意的是在gcc编译时不会出错,但是用g++就会有问题,究其原因就是C语言编译器允许隐含性的将一个通用指针转换为任意类型的指针,而C++不允许。
我仔仔细细的研究了一下, 确认了两个问题:
1. 也就是说, 我之前用c语言的时候, 确实是用的gcc编译器, 而现在用的是g++编译器, 这是编译器导致的问题.
2. g++为什么会导致这个问题, 是因为上面文字说了, g++里面的定义," 这个call中的第三个参数是载入一个函数,这个函数有一个参数可以传入,返回一个 通用指针。" 而gcc要求的是:取一个指向函数main_thread的指针,然后将其转换为一个通用指针,它们俩对参数的要求是不一样的.
所以, 从这里可以确定, 下面这种调函数的方法才是正确滴:
pthread_create(&m_tid, NULL,ThreadFunc, this);
咦, 那不是什么都没改吗? 回到最初啦. 那为什么会报错:error: argument of type 'void* (mos::CMosThread::)(void*)' does not match 'void* (*)(void*)'呢?
继续度娘,
(&tid,NULL,A::repairFileThread,NULL);
线程方法必须是静态方法,你如果写在类里,不能是成员函数,需要加static
于是乎, 我把入口函数改成static void* ThreadFunc(void * lpvParam)
编过了!!!
再尝试一下, 把这个void* ThreadFunc(void * lpvParam); 函数放到类定义的外边, 果然也编译通过了!!!
记录一下, 聊以慰藉.
阅读(19127) | 评论(0) | 转发(0) |