2014-06-23 61 views
0

我使用cURL通过http下载文件。 cURL需要一个回调来处理数据,我在我的类中有一个回调,我使用std :: bind和std :: function的组合来创建一个适当类型的函数。std :: function.target返回null

size_t NetworkResource::writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata) 
{ 
... 
} 

void NetworkResource::loadFunction(void) 
{ 
    using namespace std::placeholders; 
    typedef size_t CurlCallback(char*,size_t,size_t,void*); 
    auto function=std::function<CurlCallback>(std::bind(&NetworkResource::writeFunction,this,_1,_2,_3,_4)).target<CurlCallback*>(); 
    CURL *curl=curl_easy_init(); 
    CURLcode err; 

    ... 

    err=curl_easy_setopt(curl,CURLOPT_WRITEDATA,nullptr); 
    if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl; 

    err=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,*function); 
    if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl; 

    ... 
} 

的问题是,功能为null。根据文档,当返回的类型与函数的目标类型不匹配时会发生这种情况,但据我所知,它们确实匹配。

+0

如果这是如何试图将成员函数转换为静态函数,它不会工作。是否有一个原因,你没有'CURLOPT_WRITEDATA'将'this'传递给一个静态回调,在解压指针之后将该调用转发给非静态成员? [(见类似的问题)](http://stackoverflow.com/questions/21542723/c-segmentation-fault-caused-by-global-variable-in-separate-source-file/21542886#21542886)。 – WhozCraig

+0

为什么不能这样工作? std :: function.target返回一个指向函数指针的指针。 – user467526

回答

1
auto function = std::function<CurlCallback>(
        std::bind(&NetworkResource::writeFunction,this, 
          _1,_2,_3,_4)).target<CurlCallback*>(); 

你就构造了std::function对象将在上述表达式的末尾被销毁,而变量function就已经指出,无效的内存,必须调用std::function::target担任意。在这种情况下,它不会,函数调用返回nullptr

这是因为std::function的目标函数类型与CurlCallback的类型不同。 This example显示该呼叫有效的情况,以及失败的情况。


您可以在不使用std::function的情况下完全解决您的问题。

根据用于curl_easy_setopt,当第二个参数是CURLOPT_WRITEFUNCTION,第三个参数应该是一个指针,指向一个函数具有签名

size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata); 

最后一个参数userdata可以经由呼叫被设置为CURLOPT_WRITEDATA文档。使用它来传递指向NetworkResource实例的指针(this指针)。

至于write_callback,请创建一个静态成员函数来执行所需的功能。

class NetworkResource 
{ 
    // ... 
    static size_t writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata); 
}; 

size_t NetworkResource::writeFunction(char *ptr,size_t size,size_t nmemb,void *userdata) 
{ 
    // userdata points to the NetworkResource instance 
    auto res = static_cast<NetworkResource *>(userdata); 

    // use res and the remaining function arguments to handle the call 
} 

void NetworkResource::loadFunction(void) 
{ 
    CURL *curl=curl_easy_init(); 
    CURLcode err; 

    ... 

    err=curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,&NetworkResource::writeFunction); 
    if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl; 

    err=curl_easy_setopt(curl,CURLOPT_WRITEDATA,static_cast<void *>(this)); 
    if(err!=CURLE_OK) std::cout<<curl_easy_strerror(err)<<std::endl; 

    ... 
} 
+0

我没有通过一个std ::函数curl_easy_setopt,我传递了一个函数指针。 std :: function.target返回一个指向函数指针的指针。 – user467526