Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Sending lambda to CURLOPT_WRITEFUNCTION crashes?

I have the following code:

std::string stream;

curl_easy_setopt(curl, CURLOPT_WRITEDATA, & stream);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void *buffer, size_t size, size_t count, std::string *stream) -> size_t {
  auto s_size = size * count;
  stream->append((char *)buffer, 0, s_size);
  return s_size;
});

It compiles and it crashes. If I replace the lambda by a function, it works fine:

static size_t _writefunction(void *buffer, size_t size, size_t count, std::string *stream) {
  auto s_size = size * count;
  stream->append((char *)buffer, 0, s_size);
  return s_size;
}

Is there any way to use a lambda instead of a separated function?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

curl_easy_setopt is documented with the signature

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);

where the parameter is allowed to be one of several types depending on the option. Clearly, (as a C API, where C has no overloading) it must be doing something strange, and this is borne out by looking at the source, where we see curl_easy_setopt is implemented with varargs.

CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);

So the problem with passing a lambda to curl_easy_setopt is that it is getting passed in as is, since curl_easy_setopt says it can take objects of any type. The actual object represented by a lambda expression is just a struct of the captures; in this case, you’re just passing an empty struct object to curl_easy_setopt when it is expecting a function pointer. Chaos ensues.

Lambdas with no captures may be explicitly converted to function pointers by using unary +.

//                                            v one char fix!
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](void *buffer, size_t size, size_t count, std::string *stream) -> size_t {
  auto s_size = size * count;
  stream->append((char *)buffer, 0, s_size);
  return s_size;
});

This conversion can also happen implicitly, but curl_easy_setopt doesn’t provide any type information and thus doesn’t trigger the conversion automatically.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading