2014-12-05 86 views
0
struct BufferStruct 
{ 
char * buffer; 
size_t size; 
}; 

// This is the function we pass to LC, which writes the output to a BufferStruct 
static size_t WriteMemoryCallback 
(void *ptr, size_t size, size_t nmemb, void *data) 
{ 
size_t realsize = size * nmemb; 

struct BufferStruct * mem = (struct BufferStruct *) data; 

mem->buffer = realloc(mem->buffer, mem->size + realsize + 1); 

if (mem->buffer) 
{ 
memcpy(&(mem->buffer[ mem->size ]), ptr, realsize); 
mem->size += realsize; 
mem->buffer[ mem->size ] = 0; 
} 
return realsize; 
} 

我发现这个here了解BufferStruct + WriteMemoryCallback

什么,他想在这里做什么?特别是通过乘以这些size_t的? 他正试图展示如何将您获得的html代码导出到文件。 为什么要写这样一个复杂的(对我来说)函数呢? 谢谢如果有人可以解释或张贴一些可以帮助我理解这一点的来源:)

+1

标准库中有几个函数使用*元素数* x *元素大小*的概念,而不是简单的字节数(例如'calloc')。这是一个回调函数。它所做的就是将提供的数据复制到动态扩展的内存缓冲区中。 – 2014-12-05 23:25:32

+0

参数记录在CURLOPT_WRITEFUNCTION的文档中,我假设您使用的是,尽管您没有这么说...您的摘录是一段名为getinmemory.c的官方libcurl示例代码 – 2014-12-08 23:54:58

回答

1

下面的代码是“C”的做法.. libCurl是一个C库(也有C++包装器):

struct BufferStruct 
{ 
    char* buffer; 
    size_t size; 
}; 

static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) 
{ 
    size_t realsize = size * nmemb; //size is the size of the buffer. nmemb is the size of each element of that buffer. 
    //Thus realsize = size * sizeof(each_element). 

    //example: size_t realsize = size * sizeof(char) or size_t realsize = size * sizeof(wchar_t) 
    //Again: size is the buffer size and char or wchar_t is the element size. 

    struct BufferStruct* mem = (struct BufferStruct*) data; 

    //resize the buffer to hold the old data + the new data. 
    mem->buffer = realloc(mem->buffer, mem->size + realsize + 1); 

    if (mem->buffer) 
    { 
     memcpy(&(mem->buffer[mem->size]), ptr, realsize); //copy the new data into the buffer. 
     mem->size += realsize; //update the size of the buffer. 
     mem->buffer[mem->size] = 0; //null terminate the buffer/string. 
    } 
    return realsize; 
} 

这就是做事的 “C” 的方式..

C++的方式如下:

static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) 
{ 
    size_t realsize = size * nmemb; 

    std::string* mem = reinterpret_cast<std::string*>(data); 
    mem->append(static_cast<char*>(data), realsize); 

    return realsize; 
} 

然后在某处你的代码做的事:

std::string data; //create the std::string.. 
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); //set the callback. 
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data); //pass the string as the data pointer. 
+0

您好,非常感谢您回复。我仍然有一个问题:为什么你必须创建这些函数参数?如果我理解正确,那么您将curl_easy_setopt函数的函数指针作为参数,以便使用您的写函数而不是您的函数指针,是吗?那么我怎么才能知道我自己的函数如何看起来像使用curl类呢?谢谢 – 2014-12-07 01:48:15

+0

我不明白你的问题。这些函数参数在libcurl回调中定义:http://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html它意味着如果你想让curl使用你的函数,它必须有这些参数(签名)。你的函数看起来像“WriteMemoryCallback”。这是您的自定义功能。 – Brandon 2014-12-07 02:12:53

0

它看起来像BufferStruct是打包的数据指示字和数据大小一起的方法。这是一件好事,因为你当然不想让那些困惑。

乘法是取nmemb,aka成员数量和size,即一个成员的大小以获得完整的大小。并且在realloc中添加一个以为空字符串终止符腾出空间。空字符串结束符就是安全的。毕竟,通过curl读取的数据可以很容易地作为文本文件的JPEG图像。

此功能的必要性?那么,它会收集curl读入单个缓冲区的所有数据。这并不是必须的。代替将其写入内存的函数,您可以调用fwrite在每个回调中写入文件。实际上,功能参数设计为几乎匹配fwrite