【问题标题】:Use C++11 lambdas as callbacks in GObject library在 GObject 库中使用 C++11 lambda 作为回调
【发布时间】:2014-02-21 08:03:17
【问题描述】:

不捕获任何内容的 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 lambda:

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

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

更新

澄清一下,我知道如果签名匹配,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);

【问题讨论】:

  • 我自己没有尝试过,但您可以尝试将 lambda 存储为变量 (auto fun = [](...){...};),然后在 do_something 调用 (do_something(reinterpret_cast<void(*)()>(fun));) 中进行显式转换。由于我没有尝试过,我不知道它是否有效。
  • @icepack 这个问题不是关于如何使用 lambdas 代替函数指针。这是关于如何(如果可能)使用任意类型的 lambda 代替 GCallback。
  • @Kentzo 我明白这一点。如果您仔细研究该答案,您会发现并非总是可以将 lambdas 替换为 C 指针

标签: c++11 lambda gobject


【解决方案1】:

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

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

【讨论】:

  • 请查看我的问题的更新。第二个表达式在 C++11 下是否有效?如果是这样,你能指出标准吗?
  • 我看这个转换没有问题,lambda函数只是匿名类的一个方法。它就像正常功能一样存在。我不能指出标准,对不起,我太懒了:)
【解决方案2】:

以下代码为我编译和工作(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));

【讨论】:

    猜你喜欢
    • 2014-03-31
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 2011-09-29
    相关资源
    最近更新 更多