8

由于我最近的最后一个问题不幸措辞并导致解决了另一个问题,然后是我的问题,因此我将尝试以清晰的方式阐述我的实际问题。

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

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

在这段代码中,InvocationCallback只是一个带有签名的函数的 typedef 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 Engine 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-pointer 之后转换 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>();

}
4

2 回答 2

5

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

在 Stack Overflow 上搜索“要回调的成员函数”,您就会知道(基本上,您希望使用成员函数 the operator(),作为回调)。

于 2013-04-01T20:32:45.697 回答
0

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

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

于 2015-02-05T07:24:57.480 回答