【问题标题】:libcurl callbacks w/c++ class memberslibcurl 回调 w/c++ 类成员
【发布时间】:2011-11-02 00:01:41
【问题描述】:

取自 libcurl 网站上的libcurl programming tutorial

libcurl 与 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++ libcurl


【解决方案1】:

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

相反,静态成员函数是具有特定范围的“普通”函数(与 ABI 无关)。

【讨论】:

    【解决方案2】:

    要调用实例方法,您需要一个实例来调用它。采用函数指针的 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 成为标准并被编译器支持时,您应该能够使用闭包来绑定实例和实例方法,将匿名函数作为回调传递。

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

    【讨论】:

      猜你喜欢
      • 2011-08-23
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      • 2010-11-03
      相关资源
      最近更新 更多