2017-07-28 144 views
0

我不得不被称为C语言函数:如何从lambda表达式获取函数指针?

f_api(void(*callback)(int)) 

,我有回调类的静态方法:

struct A { 
    static void CallBack(int i) { 
     A::count = i; 
    } 
    static count = 0; 
}; 

我可以调用该函数是这样的:

f_api(&A::CallBack) 

但是,我必须现在将回调更改为非静态,因为我必须创建多个A对象。

但我不能改变f_api()的定义。

我试图用一个lambda:

f_api([this](int i)->void{this->count = i;})` 

但这个失败了,因为我不能转换拉姆达与捕捉到一个简单的函数指针。

std::bind()也不能做的工作,因为f_api()的定义。

我能为此做些什么?我如何从lambda表达式获取函数指针?有什么方法可以避开吗?

+0

你已经排除了lambda作为一个解决方案,那么你为什么又问了一遍?无论如何,API是否允许您将用户定义的值传递给回调函数?如果是这样,那就用它来传递你的'this'指针。否则,你是SOL而不诉诸使用低级thunk。 –

+0

没有什么可以做的。没有用于从成员函数指针形成常规函数指针的标准工具。如果您无法更改回调API,您将别无选择,只能通过常规功能以某种方式路由回调。 – AnT

+0

@SilvioMayolo这有点不同..我发布了一个可能会帮助别人的解决方案,尽管它对我没有任何用处。 –

回答

3

如果你不能改变C API,那么我认为你不能对这种情况做很多事情。因为C函数需要所有需要作为函数参数传入的信息。

您可以转换lambda表达式到函数指针有以下

void (*ptr)() = []() {} 

lambda表达式没有任何捕获被隐式转换为函数指针。但是捕获值的lambda不能转换为函数指针,因为它们具有额外的状态(以成员变量的形式)。

在C中解决此问题的常用方法是使用void*参数。看看pthread_create函数。线程启动函数接受一个指向“上下文”的参数为void*的函数。在你的情况下,这个上下文可以像你调用方法的实例一样。

但是,如果您无法更改C API,那么我担心您无法在函数指针上做太多的工作。你可以做的唯一事情就是使变量全局化,然后用这些变量在函数指针中调用这些方法。

+0

“让变量成为全球变量”,并保护那些带有互斥或类似功能的变量 – Caleth

0

这是我在想什么: 也许我不能通过从lambda获取函数指针来做到这一点。但我做一些其他蜱得到的多为回避这个问题...

template<unsigned int ClassCount> 
struct A { 
    static void CallBack(int i) { 
     A::count = i; 
    } 
    static int count; 
}; 

template<unsigned int ClassCount> 
int A<ClassCount>::count = 0; 

这样我就可以:

f_api(&A<0>::CallBack); 
std::cout << A<0>::count << std::endl; 
f_api(&A<1>::CallBack); 
std::cout << A<1>::count << std::endl; // A<0>::count is different from A<1>::count 

这将然而可悲的是,不能在某些情况下,潜在的解决方案,在矿井里。