【问题标题】:How to bind a std::function to JavaScript V8?如何将 std::function 绑定到 JavaScript V8?
【发布时间】:2013-03-31 16:32:05
【问题描述】:

我刚开始使用JavaScript V8 并从Embedder's Guide 编译了一个基本示例。现在我想将 C++ 函数绑定到 JavaScript 上下文。

目前我只有一个或多或少的空白类,稍后应该处理绑定。

class Manager
{
public:
    Manager()
    {
        context = Context::New();
    }
    void Bind(string Name, function<Handle<Value>(const Arguments&)> Function)
    {
        // bind the function to the given context
    }
private:
    Persistent<Context> context;
};

如何将std::function 对象绑定到 JavaScript V8 上下文?

【问题讨论】:

  • 我曾经将我的引擎中的函数与void BindExample(v8::Handle&lt;v8::ObjectTemplate&gt; engine) { engine-&gt;Set(v8::String::New("FunctionInJS"), v8::FunctionTemplate::New(FunctionInCPP)); } 之类的东西绑定在一起。这有什么帮助吗?
  • 这对我有帮助,但在您的示例中,名为 engine 的句柄到底是什么?但实际上主要问题是关于将std::function 作为参数传递。
  • 请参考我在答案中的完整示例以及我对 std::function 的尝试建议。

标签: javascript c++ binding v8 std-function


【解决方案1】:

我在引擎中使用的是一种相当复杂的方法,但我是第一个想到的。 (遗憾的是,我从 V8 迁移到 LLVM,因此我没有对此进行优化。)

void ExposeFunctions(v8::Handle<v8::ObjectTemplate> engine) {
    /* ... */
    engine->Set(v8::String::New("Exit"), v8::FunctionTemplate::New(NativeExit));
    engine->Set(v8::String::New("Log"), v8::FunctionTemplate::New(NativeLog));
    /* ... */
}

int SpawnEngine() {
    v8::Locker locker;
    v8::HandleScope handleScope;
    v8::TryCatch exceptionManager;
    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
    ExposeFunctions(global);
    v8::Persistent<v8::Context> context = v8::Context::New(nullptr, global);
    v8::Context::Scope scope(context);
    /* ... */
    context.Dispose();
    return 0;
}

这至少应该为您提供一种可能的解决方案,将本机函数绑定到解释器,您可以根据需要对其进行重新设计。

考虑到您使用函数对象的问题,可以尝试(只是在这里猜测)直接传递它,就像我对命名函数所做的那样,或者将它嵌套在传递给 v8::FunctionTemplate::New 的 lambda 表达式中。但是自从我使用它以来已经有一段时间了。

【讨论】:

    【解决方案2】:

    Set函数请求的参数类型InvocationCallback是一个简单的typedef。

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

    因此,我必须将 std::function 转换为原始函数指针。

    void Register(string Name, function<Handle<Value>(Arguments const &)> Function)
    {
        InvocationCallback* function = Function.target<InvocationCallback>();
        globals->Set(String::New(Name.c_str()), FunctionTemplate::New(*function));
    }
    

    【讨论】:

    • 我认为您不应该接受这个答案,因为正如您在另一个问题中发现的那样,这不适用于一般情况。
    • @minexew 能否提供您所指的其他问题的链接?
    猜你喜欢
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2013-06-12
    相关资源
    最近更新 更多