在GObject库中使用C ++ 11 lambdas作为回调

时间:2014-02-21 08:03:17

标签: c++11 lambda gobject

不捕获任何内容的C ++ 11 lambda可以存储在函数指针中。只需要确保lambda接受并返回与函数指针相同的参数。

GObject库中,所有回调的类型都为void(*GCallback) (void)。但是,这个定义不会影响回调的签名:

  

用于结构定义和中的回调函数的类型   功能签名。这并不意味着所有回调函数   必须没有参数并返回void。所需的签名   回调函数由使用的上下文确定(例如,   它所连接的信号)。使用G_CALLBACK()来强制转换   回调函数到GCallback。

换句话说,可以传递这样的函数:

int my_function(int a, char b) {}

通过强制转换它的类型(这就是G_CALLBACK所做的):

do_something(G_CALLBACK(my_function));

不幸的是,类型转换不适用于C ++ 11 lambdas:

do_something(G_CALLBACK([](int a, char b) -> int {...});
// Cannot cast from type lambda to pointer type GCallback

是否可以使用任意类型的C ++ lambdas代替GCallback?

更新

为了澄清,我知道如果lambda的签名匹配,lambda可以被转换为函数指针。我的问题是另一个方面。

ISO C标准保证功能可以前后进行,而不会失去任何精度。换句话说,以下表达式有效:

int f(int a){...}

void (*void_f)() = (void (*)())f;
int (*restored_f)(int) = (int (*)(int))void_f;
restored_f(10);

我的问题是根据C ++ 11,以下表达式是否也有效:

int (*f)(int) = [](int a) -> int {};
void (*void_f)() = (void (*)())f;
int (*restored_f)(int) = (int (*)(int))void_f;
restored_f(10);

2 个答案:

答案 0 :(得分:0)

Lambdas没有捕获are implicitly convertible指向标准的函数的指针。虽然目前并非所有编译器都支持此功能(https://stackoverflow.com/a/2935230/261217)。

然后您可以显式地将函数指针强制转换为GCallback

答案 1 :(得分:0)

以下代码编译并适用于我(MSVC 2013):

auto lambdaFunc = [](int a, char b) -> int { return 0; };

typedef int (*LambdaType)(int, char);

GCallback fnTest1 = G_CALLBACK((LambdaType)lambdaFunc);
GCallback fnTest2 = G_CALLBACK((LambdaType) [](int a, char b) -> int { return 0; });

do_something(fnTest1);
do_something(fnTest2);
do_something(G_CALLBACK((LambdaType)lambdaFunc));