libcurl回调w / c ++类成员

时间:2011-11-02 00:01:41

标签: c++ libcurl

取自libcurl网站上的libcurl programming tutorial

  

libcurl with C ++

     

使用C ++时,基本上只需要记住一件事   当连接libcurl时,而不是C:

     

回调不能是非静态类成员函数

     

示例C ++代码:

class AClass 
{   
    static size_t write_data(void *ptr, size_t size, size_t nmemb,   void ourpointer)       
    {   /* do what you want with the data */   }  
}

这是什么限制,是否是范围问题?如果每个类成员都拥有它自己的easy_handle,那么它可以使用回调它自己的非静态成员函数吗?它没有继续说。我可以用这种方式工作,但我很好奇为什么它存在。

编辑:还有一件事;这是否限制了从类中创建easy_handle?如果是这样,这对我的设计会造成很大的问题,我希望每个对象都有自己的easy_handle。

2 个答案:

答案 0 :(得分:2)

非静态成员函数通常不允许作为C回调,因为它还需要将实例指针作为隐藏参数,而调用C代码不提供该隐式参数(这个隐藏参数可能取决于编译器,不能根据"常规"调用约定传递,但在特定的寄存器中,...)。

相反,静态成员函数是"正常"具有特定范围的函数(就ABI而言,这是不相关的)。

答案 1 :(得分:0)

要调用实例方法,您需要一个实例来调用它。带有函数指针的libcurl函数也不会接受对象指针(相反,它们不能,因为它们是C函数),所以没有办法传递必要的数据来调用实例方法。

您可以通过userdata参数传递实例指针,然后使用它来调用实例方法:

class AClass {
public:
    static size_t invoke_write_data
        (void *data, size_t size, size_t nmemb, void* pInstance)       
    {
        return ((AClass*)pInstance)->write_data(ptr, size, nmemb);
    }

    size_t write_data(void *data, size_t size, size_t nmemb) {
        /* ... */
    }
};

...
    extern AClass instance;

    curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, AClass::invoke_write_data);
    curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, &instance);

如果需要通过userdata参数传递更多数据,请使用包含实例指针作为成员的结构。注意内存管理:参数struct最终可能会泄漏或被提前回收。

当C ++ 0x成为编译器的标准和支持时,您应该能够利用闭包来绑定实例和实例方法,并将匿名函数作为回调传递。

另请参阅:C ++ FAQ中的“How do I pass a pointer-to-member-function to a signal handler, X event callback, system call that starts a thread/task, etc?”。