2016-08-05 42 views
0

我一直在抓我的頭這個好幾個小時,我試圖從CURLINFO_PRIVATE訪問我的結構,但GCC似乎並沒有認識到它作爲一個結構:如何在libcurl中使用CURLINFO_PRIVATE訪問結構?

10-at-a-time.c: In function 'main': 
10-at-a-time.c:148:48: error: request for member 'size' in something not a structure or union 
printf("%lu bytes retrieved\n", (long)chunk->size); 
              ^
10-at-a-time.c:152:15: error: request for member 'memory' in something not a structure or union 
free(chunk->memory); 

在libcurl的文檔,它說它會返回一個字符指針:https://curl.haxx.se/libcurl/c/CURLINFO_PRIVATE.html

據我所知,我應該能夠使用「 - >」語法取消引用該指針並獲取結構實例。但這似乎並不奏效。

這裏是我的代碼,我希望這是很容易理解:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h>  

#include <curl/multi.h>  

struct MemoryStruct { 
    char *memory; 
    size_t size; 
}; 

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) { 
    size_t realsize = size * nmemb; 
    struct MemoryStruct *mem = (struct MemoryStruct *)userp; 

    mem->memory = realloc(mem->memory, mem->size + realsize + 1); 
    if(mem->memory == NULL) { 
     /* out of memory! */ 
     printf("not enough memory (realloc returned NULL)\n"); 
     return 0; 
    } 

    memcpy(&(mem->memory[mem->size]), contents, realsize); 
    mem->size += realsize; 
    mem->memory[mem->size] = 0; 

    return realsize; 
}  

static const char *urls[] = { 
    "http://www.microsoft.com", 
    "http://www.opensource.org", 
    "http://www.google.com", 
    "http://www.bbc.co.uk", 
    "http://www.newslink.org", 
    "http://www.un.org", 
    "http://www.news.com", 
    "http://www.cnn.com", 
    "http://www.wikipedia.org", 
    "http://www.dell.com", 
    "http://www.hp.com", 
    "http://www.cert.org", 
    "http://www.mit.edu", 
    "http://www.nist.gov", 
    "http://www.ebay.com", 
    "http://www.playstation.com", 
    "http://www.uefa.com", 
    "http://www.ieee.org", 
    "http://www.apple.com", 
    "http://www.symantec.com" 
}; 

#define count sizeof(urls)/sizeof(char*) 

static void init(CURLM *cm, int i) 
{ 
    CURL *eh = curl_easy_init();  

    struct MemoryStruct chunk; 

    chunk.memory = malloc(1); /* will be grown as needed by the realloc above */ 
    chunk.size = 0; /* no data at this point */  

    curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 
    curl_easy_setopt(eh, CURLOPT_WRITEDATA, (void *)&chunk); 
    curl_easy_setopt(eh, CURLOPT_HEADER, 0L); 
    curl_easy_setopt(eh, CURLOPT_URL, urls[i]); 
    curl_easy_setopt(eh, CURLOPT_PRIVATE, (void *)&chunk); 
    curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L); 
    curl_multi_add_handle(cm, eh); 
} 

int main(void) 
{ 
    int bots = 10;  

    if (count < bots) { 
     bots = count; 
    }  

    CURLM *cm; 
    CURLMsg *msg; 
    long L; 
    struct timeval timeout; 
    unsigned int current = 0;  

    int msg_queue = -1; 
    int handles = -1; 
    int maxfd = -1;  

    fd_set fdread; 
    fd_set fdwrite; 
    fd_set fdexcep;  

    curl_global_init(CURL_GLOBAL_ALL); 
    cm = curl_multi_init();  

    curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)bots); 

    for (current = 0; current < bots; ++current) { 
     init(cm, current); 
    } 

    while (handles) { 
     curl_multi_perform(cm, &handles); 

     if (handles) { 
      FD_ZERO(&fdread); 
      FD_ZERO(&fdwrite); 
      FD_ZERO(&fdexcep); 

      if (curl_multi_fdset(cm, &fdread, &fdwrite, &fdexcep, &maxfd)) { 
       fprintf(stderr, "E: curl_multi_fdset\n"); 
       return EXIT_FAILURE; 
      } 

      if (curl_multi_timeout(cm, &L)) { 
       fprintf(stderr, "E: curl_multi_timeout\n"); 
       return EXIT_FAILURE; 
      }  

      if (L == -1) { 
       L = 100; 
      } 

      if (maxfd == -1) { 
       sleep((unsigned int)L/1000); 
      } 
      else { 
       timeout.tv_sec = L/1000; 
       timeout.tv_usec = (L % 1000) * 1000; 

       if (0 > select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout)) { 
        fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n", maxfd + 1, L, errno, strerror(errno)); 
        return EXIT_FAILURE; 
       } 
      } 
     } 

     while ((msg = curl_multi_info_read(cm, &msg_queue))) { 
      if (msg->msg == CURLMSG_DONE) { 
       char *chunk; 
       CURL *e = msg->easy_handle; 
       curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &chunk); 
       fprintf(stderr, "R: %d - %s\n", msg->data.result, curl_easy_strerror(msg->data.result));  

       printf("%lu bytes retrieved\n", (long)chunk->size); 

       curl_multi_remove_handle(cm, e); 
       curl_easy_cleanup(e); 
       free(chunk->memory); 
      } 
      else { 
       fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg); 
      }  

      if (current < count) { 
       init(cm, current++); 
       handles++; 
      } 
     } 
    } 

    curl_multi_cleanup(cm); 
    curl_global_cleanup(); 

    return EXIT_SUCCESS; 
} 

我是新的C BTW。

回答

0

設置專用指針:

ptr = [something]; 
curl_easy_setopt(curl, CURLOPT_PRIVATE, ptr); 

從手柄再次提取指針它在設置:

curl_easy_getinfo(curl, CURLINFO_PRIVATE, &ptr); 

在你的情況,當你再次提取指針,你需要確保你有它作爲正確的結構指針,而不僅僅是一個char *。也許像:

struct MemoryStruct *chunk; 
curl_easy_getinfo(curl, CURLINFO_PRIVATE, &chunk); 

...因爲你可以訪問結構及其字段。

+0

非常感謝Daniel,完美的作品。我不認爲這會很容易:) – sasha