我有以下代码:
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 代替分离的函数吗?
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_setopt
struct
struct
curl_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
不提供任何类型信息,因此不会自动触发转换。