在C ++中的C风格回调11 [英] C-style Callbacks in C++11

查看:141
本文介绍了在C ++中的C风格回调11的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



为了实现这一点,我使用了poiner-to-member操作符:

  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(){
//注册回调函数
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,c_callback_wrapper);
//注册userdata
curl_easy_setopt(curl,CURLOPT_WRITEDATA,this);
...
res = curl_easy_perform(curl);
}

这个解决方案实际上有效,但对我来说不太满意。

我实际想要做的是在我的注册函数中写一个lambda。



我将能够捕获一些局部变量,并且不需要编写一个复杂的actualCallback成员例程。



我已经读过,似乎不是可能使用Lambdas作为C风格函数,当他们捕获变量。



有什么方法来实现这一使用一些技巧? (例如使用lambdas的调用约定...)



感谢

解决方案

捕获上下文变量的lambda不能转换为裸函数指针,因为这将使得不可能携带捕获的状态。在示例中显示的是正确的方式来处理通过C回调调用C ++成员函数的问题。



如果您发现任何更有吸引力的话,您可以用一个少量的lambda替换 c_callback_wrapper

  curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,
[](char * ptr,size_t size,size_t nmemb,void * userdata){
//通过userdata调用成员函数
auto p = static_cast< MyClass *>(userdata);
return p> actualCallback(ptr,size,nmemb,userdata);
});

注意,你应该删除 actualCallback )成员函数,因为这只是这个指针,非静态成员函数不应该明确传递。 p>

In a C++11 project I'm using a C-style third-party library (curl in my case) which needs C-style callbacks.

To achieve this I used the "poiner-to-member" operator:

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);
}

This solution actually works, but it's not satisfying for me.

What I actually want to do is to write a lambda inside my registering function.

The advantage would be locality in general: I would be able to capture some local variables and there would be no need to write a complex "actualCallback" member routine.

I already read, that it seems not to be possible to use Lambdas as C-style Functions when they capture variables.

Are there any ways to achieve this using some tricks? (e.g. playing with the calling convention of lambdas, ...)

Thanks

解决方案

A lambda that captures context variables cannot be converted to a bare function pointer because that would make it impossible to carry the captured state along. What you've shown in the example is the right way to go about dealing with the problem of invoking C++ member functions via a C callback.

You could replace c_callback_wrapper with a capture less lambda, if you find that any more appealing.

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);
                 });

Note that you should probably get rid of the last parameter to the actualCallback() member function, since that is just the this pointer, which the non-static member function shouldn't need to be passed explicitly.

这篇关于在C ++中的C风格回调11的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆