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

Convert lambda with capture clause stored in std::function to raw function pointer

本文关键字:指针 lambda 子句 转换 原始 函数 std 存储 function      更新时间:2023-10-16

由于我上一个问题的措辞很不幸,并导致了另一个问题的解决方案,这里我将尝试以一种清晰的方式阐述我的实际问题。

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

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

在这段代码中,InvocationCallback只是一个带有Handle<Value>(Arguments const &)签名的函数的类型定义。

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引用或this指针之后转换lambda。

更新:由于似乎不可能从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>();
}

不能,因为捕获的lambda是闭包,所以它有状态(它是一个具有实例变量的对象)。函数指针没有状态。因此,你不能做到这一点,除非1)你正在使用的API要求函数指针也允许你在传递状态的地方传递用户数据参数,或者2)将状态存储在全局变量或其他东西中。

在Stack Overflow周围搜索"回调的成员函数",你会得到一个想法(基本上,你想使用一个成员函数,operator(),作为回调)。

您可以将捕获lambda/函子转换为函数指针,但在这样做时需要小心:

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