2014-06-23 43 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