取自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。
答案 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?”。