Понимание BufferStruct + WriteMemoryCallback

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;
}

Я нашел это здесь

Что он здесь делает? Эсперантно, умножая эти size_t? Он пытается показать, как экспортировать html-код, который вы получаете в файл. Почему необходимо написать сложную (для меня) функцию? Спасибо, если кто-то может объяснить или опубликовать какой-то источник, который может помочь мне понять это :)

  • 1
    В стандартной библиотеке есть несколько функций, которые используют концепцию количества элементов x размера элемента, а не простого количества байтов (например, calloc ). Это функция обратного вызова в том же духе. Все, что он делает, это копирует предоставленные данные в динамически расширяющийся буфер памяти.
  • 0
    Аргументы задокументированы в документации по CURLOPT_WRITEFUNCTION, которую я предполагаю, что вы используете, хотя вы этого не сказали ... Ваш отрывок является частью официального примера кода libcurl, называемого getinmemory.c
Теги:
function
libcurl

2 ответа

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++:

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? Спасибо
  • 0
    Я не поняла ваш вопрос. Эти параметры функции определены в обратном вызове libcurl: curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html это означает, что если вы хотите, чтобы curl использовал вашу функцию, он должен иметь эти параметры (подпись). Ваша функция должна выглядеть как «WriteMemoryCallback». Это ВАША пользовательская функция.
0

Похоже, что BufferStruct - это способ BufferStruct указатель данных и размер данных. Это хорошо, потому что вы, конечно, не хотите путать их.

Умножение - взять nmemb, aka Number of Members и size, aka Size of One Member, чтобы получить полный размер. И добавьте один в realloc, чтобы освободить место для нулевого ограничителя строк. Нулевой ограничитель строки просто должен быть безопасным. В конце концов, данные, считываемые curl, могли бы также быть JPEG-изображением в виде текстового файла.

Необходимость этой функции? Ну, он собирает все данные, которые завиток читал в один буфер. Это не обязательно. Вместо функции, которая записывает ее в память, вы можете вызвать fwrite для записи в файл при каждом fwrite вызове. Фактически, параметры функции рассчитаны на почти совпадение с fwrite.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню