将存储在std :: function中的带有子句的lambda转换为原始函数指针

时间:2013-04-01 18:11:27

标签: c++ binding lambda function-pointers std-function

由于我的last recent question措辞不健全并导致解决了另一个问题,因此我会在这里以明确的方式制定我的实际问题。

在开始之前,作为旁注,我正在将Javascript引擎V8集成到我的C ++应用程序中。这就是示例中所有类型的来源。这也是我最终需要一个原始函数指针这一事实的原因。但我在下面详细说明。

从类中我需要将带有捕获子句[=]的lambda表达式作为类型std::function的参数传递给另一个函数,然后将其转换为原始函数指针。

在此代码中,InvocationCallback只是具有签名Handle<Value>(Arguments const &)的函数的typedef。

typedef Handle<Value> (*InvocationCallback)(Arguments const &);

void Bind(string Name, function<Handle<Value>(Arguments const &)> Function)
{
    InvocationCallback* function = Function.target<InvocationCallback>();
}

所有lambda表达式也具有相同的签名。请注意,在此示例中,Handle<String>Handle<Value>兼容。它也是由Javascript引擎V8提供的。

Bind("name", [=](const Arguments& args) -> Handle<Value>{
    Handle<String> result = String::New(Name().c_str());
    return result;
});

C ++允许我将此lambda作为std::function传递给上面的函数。但是我猜一个lambda表达式也存储了对它引用的对象的引用。不知何故必须实现[=]指定的访问权限。这可能是将std::function转换为原始函数指针失败的原因。

InvocationCallback* function = Function.target<InvocationCallback>();

既没有编译时错误也没有运行时错误,但调试器告诉我它导致空指针。但我需要原始函数指针进行进一步处理。我想我可以在引用std::bind之后转换lambda,或者首先转换this - 指针。

更新:由于似乎不可能将状态从lambda中取出,这就是我尝试过的。它编译,但function出来是一个空指针。

Bind("name", this, [](Base* object, const Arguments& args) -> Handle<Value>{
    return v8::String::New(((Derived*)object)->Name().c_str());
});

void Bind(string Name, Module *Object, function<Handle<Value>(Module*, Arguments const &)> Function)
{
    function<Handle<Value>(Arguments const &)> method = std::bind(Function, Object, std::placeholders::_1);
    InvocationCallback* function = method.target<InvocationCallback>();

}

2 个答案:

答案 0 :(得分:5)

你不能,因为捕获的lambda是闭包,所以它有状态(它是一个带有实例变量的对象)。函数指针没有状态。因此,如果没有1)您正在使用的API需要函数指针也允许您传递用于传递状态的用户数据参数,或者2)将状态存储在全局变量中,则不能这样做。

在Stack Overflow中搜索“成员函数回调”,你会得到一个想法(基本上,你想要使用成员函数operator()作为回调)。

答案 1 :(得分:0)

您可以将捕获lambda / functor转换为函数指针,但在执行此操作时需要小心:

https://codereview.stackexchange.com/questions/79612/c-ifying-a-capturing-lambda