C++11 中的 C 风格回调

rra*_*alf 5 c++ lambda curl callback c++11

在 C++11 项目中,我使用的是 C 风格的第三方库(在我的例子中是 curl),它需要 C 风格的回调。

为了实现这一点,我使用了“指针到成员”运算符:

size_t c_callback_wrapper(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    MyClass *p = (MyClass*)userdata;
    return (p->*&MyClass::actualCallback)(ptr, size, nmemb, userdata);
}


void Myclass::performSomething() {
    // register callback function
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, c_callback_wrapper);
    // register userdata
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
    ...
    res = curl_easy_perform(curl);
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案确实有效,但对我来说并不令人满意。

我真正想做的是在我的注册函数中编写一个 lambda。

优势通常是局部性:我将能够捕获一些局部变量,并且无需编写复杂的“actualCallback”成员例程。

我已经读过,当 Lambda 捕获变量时,似乎不可能将它们用作 C 风格的函数。

有什么方法可以使用一些技巧来实现这一目标吗?(例如玩 lambdas 的调用约定,...)

谢谢

Pra*_*ian 5

无法将捕获上下文变量的 lambda 转换为裸函数指针,因为这将无法携带捕获的状态。您在示例中展示的是处理通过 C 回调调用 C++ 成员函数的问题的正确方法。

c_callback_wrapper如果您发现更吸引人,您可以替换为捕获较少的 lambda。

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, 
                 [](char *ptr, size_t size, size_t nmemb, void *userdata) {
                    // invoke the member function via userdata
                    auto p = static_cast<MyClass *>(userdata);
                    return p->actualCallback(ptr, size, nmemb, userdata);
                 });
Run Code Online (Sandbox Code Playgroud)

请注意,您可能应该去掉actualCallback()成员函数的最后一个参数,因为那只是this指针,非静态成员函数不需要显式传递指针。