我可以将libcurls CURLOPT_WRITEFUNCTION与C++ 11 lambda表达式一起使用吗?

Str*_*yer 9 c++ lambda libcurl c++11

我尝试使用带有CURLOPT_WRITEFUNCTION的C++ 11 lambda表达式,但程序在运行时因访问冲突而崩溃.由于缺乏C++ 11知识,我不确定如何进一步研究这个问题,但也许其他人知道如何使这项工作.

功能:

#ifndef CURL_GET_H
#define CURL_GET_H

#include <curl/curl.h>
#include <curl/easy.h>
#include <vector>
#include <string>

std::vector<std::string> curl_get(const char* url)
{
    CURL *curl;
    CURLcode res;

    std::vector<std::string> content;
    auto curl_callback = [](void *ptr, size_t size, size_t nmemb, void *stream) -> size_t {
        // does nothing at the moment due to testing...
        return size * nmemb;
    };

    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/aaa.txt");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_callback);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
    }

    return content;
}

#endif // CURL_GET_H
Run Code Online (Sandbox Code Playgroud)

错误:

在lpip_dl.exe中的Unbehandelte Ausnahme bei 0x000000cc:0xC0000005:Zugriffsverletzung bei位置0x00000000000000cc.

(位置0x00000000000000cc处的访问冲突)

当curl想要使用回调时会发生:

wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
Run Code Online (Sandbox Code Playgroud)

小智 8

你实际上可以通过将lambda函数转换为函数指针来实现.您可以先创建一个typedef来简化演员表.

typedef size_t(*CURL_WRITEFUNCTION_PTR)(void*, size_t, size_t, void*);
Run Code Online (Sandbox Code Playgroud)

然后你使用static_cast.

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, static_cast<CURL_WRITEFUNCTION_PTR>(curl_callback));
Run Code Online (Sandbox Code Playgroud)

注意:为了转换为C函数指针,您只能使用空捕获[].

  • @AndréPuel所有无状态lambda函数都有一个隐式运算符转换为函数指针.在我使用的调用约定支持的每个编译器中,它甚至支持convert-to-arbitrary-calling-convention-function-pointer.您甚至不必显式转换,只需初始化相应类型的变量即可.需要进行转换,因为没有它,您将无状态lambda直接粘贴到堆栈上,而不是引擎期望的函数指针.见[http://stackoverflow.com/questions/25513380/c-style-callbacks-in-c11/25533447#25533447] (3认同)

小智 6

这可以通过 + 前缀来完成,它返回一个 C 风格的函数指针。但这仅适用于无状态 lambda(空捕获列表,即 [])。

auto lambda = +[](void *ptr, size_t size, size_t nmemb, void *stream) -> size_t {
    // does nothing at the moment due to testing...
    return size * nmemb;
};
Run Code Online (Sandbox Code Playgroud)

或者

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](void *ptr, size_t size, size_t nmemb, void *stream) -> size_t {
    // does nothing at the moment due to testing...
    return size * nmemb;
});
Run Code Online (Sandbox Code Playgroud)


Dan*_*erg 3

libcurl 是纯 C 库,您需要设置一个可以从此类库调用的回调。这意味着有趣的 C++ 东西需要首先“C'ified”才能工作。就像旧式的函数指针一样。

libcurl FAQ 条目“使用 C++ 非静态函数进行回调? ”中也解决了这个问题。

另请参阅:C++11 中的 C 风格回调