【问题标题】:How to get a function pointer from lambda expressions or so? [duplicate]如何从 lambda 表达式中获取函数指针? [复制]
【发布时间】:2018-01-03 23:39:16
【问题描述】:

我有一个 C 语言函数要调用:

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

但这失败了,因为我无法将带有捕获的 lambda 转换为简单的函数指针。

std::bind() 也无法完成这项工作,因为 f_api() 定义。

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

【问题讨论】:

  • 你已经排除了 lambda 作为解决方案,那你为什么还要问它呢?无论如何,API 是否允许您将用户定义的值传递给回调?如果是这样,那么使用它来传递您的 this 指针。否则,您就是 SOL,而无需使用低级 thunk。
  • 您无能为力。没有用于从成员函数指针形成常规函数指针的标准工具。如果您无法更改回调 API,您将别无选择,只能以某种方式通过常规函数路由回调。
  • @SilvioMayolo 这有点不同。我发布了一个可能对其他人有帮助的解决方案,尽管它对我没有用。
  • 如果你真的想要任何方法将 lambdas(尤其是捕获数据的闭包)转换为原始函数指针,我编写了一个小库来实现这一点。请注意,这不是生产质量代码;这只是我的一个小实验,看看你的问题是否可以解决。另请注意,我的实现仅适用于 Linux 和 OS X,但如果您想要适用于 Windows 的东西,一般的想法就在那里。 github.com/MonaTheMonad/c2fp

标签: c++ c++11 lambda


【解决方案1】:

如果您无法更改 C API,那么我认为您对这种情况无能为力。因为 C 函数需要将它们所需的所有信息作为函数参数传入。

您可以使用以下方法将 lambda 转换为函数指针

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

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

在 C 中解决这个问题的常用方法是使用void* 参数。看看pthread_create 函数。线程启动函数接受一个带有void* 参数的函数,该参数指向一个“上下文”。在您的情况下,此上下文可能类似于您正在调用该方法的实例。

但如果你不能改变 C API,那么恐怕你不能对函数指针做太多事情。您唯一能做的就是使变量成为全局变量,然后使用它们在函数指针中调用这些方法。

【讨论】:

  • “使变量全局化”并使用互斥锁或类似方法保护变量
【解决方案2】:

这是我的想法: 也许我不能通过从 lambda 获取函数指针来做到这一点。但是我做了一些其他的勾勾来让 multi-As 回避这个问题......

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

在某些情况下,这可能是一个潜在的解决方案,但遗憾的是,在矿山中却不是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多