cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Callback function gives crazy "size_t nmemb" value for simple http get operation (C++)

From: Kjetil Volden <kvolden_at_gmail.com>
Date: Sun, 05 Apr 2009 19:02:50 +0200

A. Craig West wrote:
> 2009/4/5 Phil Blundell <pb_at_reciva.com>:
>
>> On Sun, 2009-04-05 at 09:29 +0200, Kjetil Volden wrote:
>>
>>> curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Book::write_html);
>>>
>> This is your problem; the WRITEFUNCTION expects a pointer to a C
>> function, not a C++ method. You need to provide a wrapper function to
>> interface between the C and C++ worlds, or make Book::write_html be a
>> static member function rather than an object method.
>>
>
> The easiest thing to do in C++ is to pass a pointer to a static
> method. It needs to have the correct prototype, so you should declare
> it in the header as:
> static size_t write_html(char *buffer, size_t size, size_t nmemb, void *ptr);
>
> and in the .cpp (or .cc) as:
> size_t Book::write_html(char *buffer, size_t size, size_t nmemb, void* ptr) {
> std::string *html = (std::string*)ptr;
> int result = 0;
> if(buffer != NULL){
> html->append(buffer, size*nmemb);
> result = size*nmemb;
> }
> return result;
> }
>
> A fairly common thing to do if your callback needs to be a non-static
> method is to pass the this pointer as the data, and use a static
> wrapper. For example, if write_html needed to be non-static, then you
> should have two methods in the Book class:
> static size_t write_html_callback(char *buffer, size_t size, size_t
> nmemb, void* thisPtr) {
> if (thisPtr)
> return (Book*)thisPtr->write_html(buffer, size, nmemb);
> else
> return 0;
> }
> size_t write_html(char* buffer, size_t size, size_t nmemb);
> // Presumably, the place to write the html to would be stored in a
> private member variable somewhere
> // in the Book class
>
> In this case, you would call it with:
>
> Book book;
> ...
> curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Book::write_html_callback);
> curl_easy_setopt(curl, CURLOPT_WRITEDATA, &book);
>
> It is more common to have the code for setting up the callback in the
> same class as the callback, in which case you could do:
> curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_html_callback);
> curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
>
> -Craig
>
>
Thank you both! I declared the function static and changed "std::string
*html" to "void *ptr" in the declaration, and did an in-function cast to
a string pointer instead. And it works! Thanks again!

-Kjetil
Received on 2009-04-05