Libcurl回调w/c++类成员

libcurl callbacks w/c++ class members

本文关键字:成员 c++ 回调 Libcurl      更新时间:2023-10-16

摘自libcurl网站上的libcurl编程教程:

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

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

相反,静态成员函数是具有特定作用域的"普通"函数(就ABI而言,这是不相关的)。

要调用实例方法,您需要一个实例来调用它。接受函数指针的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参数传递更多数据,请使用包含实例指针作为成员的结构体。注意内存管理:参数结构可能会泄漏或被提前回收。

当c++ 0x成为标准并被编译器支持时,你应该能够使用闭包来绑定实例和实例方法,传递一个匿名函数作为回调。

参见:"如何将指向成员函数的指针传递给信号处理程序、X事件回调、启动线程/任务的系统调用等?",来自c++常见问题解答