【问题标题】:Pass a c++ lambda to old c function pointer将 c++ lambda 传递给旧的 c 函数指针
【发布时间】:2013-09-11 16:01:51
【问题描述】:

我必须为旧的 c 库创建一个 c++ 包装器。

在类方法中,我必须调用一个 c 函数,该函数与其他东西一起接受一个函数指针(它是一个事件处理程序,该函数接受一个在事件发生时触发的函数)。

一个简单的例子是这样的:

void myclass::add_handler(std::function<void()> handler, otherstuff...)
{
    /*
     *  Many things.
     */

    type_of_function_pointer_accepted_by_old_c_library_add_handler nameofvariable =
    [handler](same_arguments_as_in_definition_of_the_old_c_function_pointer_accepted)
    {
        /*
         *  Many other things with other stuff to be done before the
         *  handler but always only when fired and not when myclass::add_handler is called.
         */
        handler();
    };

    old_c_library_add_handler(nameofvariable);

    /*
     *  Last things.
     */
}

据我所知,编译器抱怨我无法将带有捕获的 lambda 分配给旧的 c 函数指针。 问题是:我该如何解决?

【问题讨论】:

  • 您不能将任何非静态成员函数传递给 c 函数指针。您必须创建一个静态函数才能将其传递给 c 函数。从该静态函数中,您必须检索要在其上调用成员函数的实例。
  • 我想我没有完全理解。我应该写一个static myclass::some_function 并将其复制到c 函数指针而不是lambda。然后在静态函数内部如何检索我在 lambda 中获取的捕获变量?你能写一些示例代码吗?
  • old_c_library_add_handler 真正的样子是什么?设计合理的 C 库通常允许传递 void* 指针或类似的指针以及回调。当他们调用回调时,他们将该指针直接传回给它,以获取上下文。看看你的图书馆是不是其中之一。如果没有,那么恐怕您将不得不求助于非便携式黑客,例如动态创建机器代码 thunk。
  • 是的,old_c_library_add_handler 采用 void* 参数,该参数是包含处理程序可以从调用方获取的内容的 blob。我不知道如何将std::function&lt;void()&gt; handler 转换为void* 参数,然后在处理程序中再次将其转换为std::function&lt;void()&gt; handler,以便我可以调用它。

标签: c c++11 lambda function-pointers wrapper


【解决方案1】:

这是一个例子。我们使用的事实是,根据 C++ 标准,不捕获任何内容的 lambda 可用作函数指针。

/* The definition of the C function */
typedef void (*PointerToFunction)();
void old_c_function(PointerToFunction handler, void* context);


/* An example of a C++ function that calls the above C function */
void Foo(std::function<void()> handler)
{
    auto lambda = [] (void* context) {
        auto handler = reinterpret_cast<std::function<void()>*>(context);
        (*handler)();
    };

    old_c_function(&lambda, &handler); 
}

我相信您可以在您的上下文中使用相同的想法。

【讨论】:

  • 这只有在 Foo 返回之前调用回调函数时才有效。如果 C 库存储函数指针并在以后调用它,它将引用无效内存。 (因为处理程序变量超出范围)
  • 确实如此。如果用户想要别的东西,他应该复制处理程序并将其作为上下文传递(然后释放它)。当然,这更复杂。
猜你喜欢
  • 2021-10-05
  • 2011-04-17
  • 2012-02-22
  • 1970-01-01
  • 2011-05-22
  • 2013-04-28
  • 2019-03-12
相关资源
最近更新 更多