将lambda转换为函数指针typedef

时间:2018-01-05 21:57:23

标签: c++ c++11 lambda callback

我有第三方API,其函数将函数指针作为参数(样本类型):

// defined in "Api.h"
typedef int (*Callback) (int x); 

unsigned char ApiCall(int p, Callback cb);


int ApiCall(int p, Callback cb) {
   return cb(p);
}

我尝试使用类实例方法与此API进行交互;这是一个示例类:

class ApiWrapper {
    public:
        int ApiCallback(int x) { return this->factor_ * x; }

        static int WorkingApiCallback(int x) { return 3 * x; }

        ApiWrapper(int f) { this->factor_ = f; }

    private:
        int factor_;
} 

要测试的主要功能:

#include <iostream>
#include <functional>

int main() {
    ApiWrapper a(2);

    using std::placeholders::_1;
    std::function<int(int)> lambda = std::bind( &ApiWrapper::ApiCallback, a, _1 );

    std::cout << "Class: "  << a.ApiCallback(21) << std::endl;
    std::cout << "Lambda: " << lambda(21) << std::endl;
    std::cout << "Static ApiCall:" << ApiCall(21, ApiWrapper::WorkingApiCallback) << std::endl;

    // NOT WORKING 
    std::cout << "Static ApiCall:" << ApiCall(21, lambda) << std::endl;
    std::cout << "Static ApiCall:" << ApiCall(21, this.ApiCallback) << std::endl;    

    return 0;
}

有没有办法在不使用static成员的情况下实现这一目标;因为每次第三方lib调用回调时我都需要关联/使用状态。

谢谢!

2 个答案:

答案 0 :(得分:0)

您将不得不以某种方式将非成员与函数指针相关联,因为它不会采用任何类型的上下文参数。你将在某个时刻拥有一个非成员函数,没有办法解决这个问题。而且这个功能不能成为捕获lambda。

一个选项是拥有一个(可能是线程本地的)全局指针来保存实例。

即。你这样做:

if(parent){
    parent.removeChild(this);
}

另一个选择是使用libffi的闭包系统在运行时创建一个函数,并让实例成为已保存数据的一部分。我经常使用这种模式,但这里粘贴起来有点复杂。

答案 1 :(得分:0)

  

有没有办法在不使用静态成员的情况下实现这一点;

有一种解决方案。

  1. 定义非成员函数。
  2. 存储指向非成员函数可以访问的对象的指针。
  3. 从非成员函数中调用对象的成员函数。
  4. ApiWrapper* objectForCallback = NULL; 
    
    int  NonMemberFunction(int x)
    {
       assert(objectForCallback != NULL);
       return objectForCallback->ApiCallback(x);
    }
    

    以及上述工作的设置:

    ApiWrapper a(2);
    objectForCallback = &a;
    

    现在你可以使用:

    std::cout << "Static ApiCall:" << ApiCall(21, NonMemberFunction) << std::endl;