将Lambda传递给CURLOPT_WRITEFUNCTION崩溃,能否用Lambda替代函数?
问题描述
我编写了如下代码:
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; });
该代码可编译但运行时崩溃。若将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; }
则程序可正常运行。请问是否可以使用Lambda替代独立函数?
解答
可以用Lambda替代独立函数,但你的写法存在签名不匹配的问题,这才是运行崩溃的根源:
- curl要求
CURLOPT_WRITEFUNCTION的回调签名必须是:size_t (*)(void* buffer, size_t size, size_t nmemb, void* userdata) - 你写的Lambda第四个参数是
std::string*,但curl实际传递的是void*类型的CURLOPT_WRITEDATA指针,类型不匹配会导致运行时未定义行为(崩溃) - 无捕获的Lambda可以隐式转换成普通C函数指针,这是Lambda能作为curl回调的前提(带捕获的Lambda无法转换成普通函数指针,不能用)
修正后的Lambda写法如下,严格匹配回调签名,内部再做类型转换:
std::string stream; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, [](void *buffer, size_t size, size_t count, void *userdata) -> size_t { const size_t s_size = size * count; auto* stream = static_cast<std::string*>(userdata); stream->append(static_cast<char*>(buffer), s_size); return s_size; });
另外你原来的普通函数写法其实也不符合curl回调的规范(第四个参数类型不匹配),只是碰巧没触发崩溃,不建议这么写,最好也改成void*参数后再转换类型。
内容的提问来源于stack exchange,提问作者Rodrigo
相关产品推荐
相关产品推荐

