将 lambda 发送到 CURLOPT_WRITEFUNCTION 会崩溃吗?

Skh*_*haz -2 c++ libcurl

我有以下代码:

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;
});
Run Code Online (Sandbox Code Playgroud)

它编译并崩溃。如果我用函数替换 lambda,它就可以正常工作:

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;
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使用 lambda 代替分离的函数吗?

HTN*_*TNW 6

curl_easy_setopt 并附有签名记录

CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
Run Code Online (Sandbox Code Playgroud)

其中parameter允许为多种类型之一,具体取决于option。显然,(作为一个 C API,其中 C 没有重载)它一定在做一些奇怪的事情,这可以通过查看源代码来证实,我们看到源代码curl_easy_setopt是用 varargs 实现的。

CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
Run Code Online (Sandbox Code Playgroud)

因此,传递 lambda 的问题是它是按原样curl_easy_setopt传递的,因为它可以接受任何类型的对象。lambda 表达式表示的实际对象只是捕获的一个;在这种情况下,您只是在需要函数指针时传递一个空对象。混乱随之而来。curl_easy_setoptstructstructcurl_easy_setopt

没有捕获的 Lambda 可以使用 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;
});
Run Code Online (Sandbox Code Playgroud)

此转换也可以隐式发生,但curl_easy_setopt不提供任何类型信息,因此不会自动触发转换。