Chinaunix首页 | 论坛 | 博客
  • 博客访问: 378515
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 560
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-10 08:38
文章分类
文章存档

2016年(32)

2015年(48)

我的朋友

分类: LINUX

2016-01-05 08:30:59


错误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); 函数放到类定义的外边, 果然也编译通过了!!!

    

     记录一下, 聊以慰藉.



阅读(19002) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~