将Lambda转换为CURL回调函数

4
我试图将一个lambda传递给CURLOPT_WRITEFUNCTION。该函数需要一个静态函数,但是我从这个问题中了解到,lambda会被隐式转换,我可以从lambda调用成员函数。
auto callback = [](char * ptr_data, size_t size, size_t nmemb, string * writerData)
->size_t
{
    if(writerData == NULL)
        return 0;
    size_t data_size = size * nmemb;
    writerData->append(ptr_data, data_size);
    return (int)data_size;
};

CURLcode code = curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, callback);

这段代码可以编译通过,但是curl会崩溃:Segmentation fault: 11

完整示例已经在这里

看了你的代码片段,难道你不想在调用CURLOPT_WRITEFUNCTION之前先调用code = curl_easy_setopt(conn, CURLOPT_WRITEDATA, &buffer);吗?否则传递给回调函数的指针将没有被设置。 - Jesse Good
@JesseGood,只要我在调用curl_easy_perform之前设置它们,顺序并不重要。 - Francisco Aguilera
2个回答

8
神奇的地方在于,在非捕获的lambda表达式前面加上"+",这将触发转换为普通的C函数指针。
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
  /* NOTE: Leader '+' trigger conversion from non-captured Lambda Object to plain C pointer */
  +[](void *buffer, size_t size, size_t nmemb, void *userp) -> size_t {
    // invoke the member function via userp
    return size * nmemb;
  });

我的理解是,curl_easy_setopt需要一个void*,而不是一个明确的函数类型,所以编译器只是给出了lambda对象的地址;如果我们对lambda对象进行函数指针操作,编译器将从lambda对象返回函数指针。

3
一个lambda闭包只有在没有捕获时才能转换为函数指针。
你的lambda捕获了[this],因此无法转换。
编辑:这是对原问题版本的回答。

虽然不是针对curl的特定问题,但这些其他问题类似。 - Drew Dormann
请查看我的编辑,我已经意识到这一点,并且正在测试不同的配置,因为在所有情况下curl仍然会崩溃。 - Francisco Aguilera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接