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: A. Craig West <acraigwest_at_gmail.com>
Date: Sun, 5 Apr 2009 10:12:40 -0400

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
Received on 2009-04-05