V8 引用非全局变量的FunctionTemplate

V8 引用非全局变量的FunctionTemplate,v8,embedded-v8,V8,Embedded V8,Google的v8文档描述了如何向JavaScript上下文添加全局函数。使用C++11中的新lambda功能,我们可以非常轻松地实现类似printf的函数: Handle<ObjectTemplate> global = ObjectTemplate::New(); global->Set(String::New("print"), FunctionTemplate::New( [](const v8::Arguments &args) -> v8::Handl

Google的v8文档描述了如何向JavaScript上下文添加全局函数。使用C++11中的新lambda功能,我们可以非常轻松地实现类似printf的函数:

Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("print"), FunctionTemplate::New(
[](const v8::Arguments &args) -> v8::Handle<v8::Value>
{
  v8::String::AsciiValue ascii(args[0]);
  std::cout << *ascii << "\n";
} ));
Persistent<Context> context = Context::New(NULL, global);

不幸的是,v8似乎不支持这一点。我假设(希望?)v8有一种做功能上等价的事情的方法,但我发现自己被
v8::FunctionTemplate
的Doxygen搞糊涂了。任何试图做类似事情的人都愿意把这个过程提炼成更容易理解的东西吗?我还想学习如何创建一个JavaScript对象的全局实例,该对象绑定到C++对象的一个现有的非全局实例。关键是要认识到v8::Arguments不仅仅是一个参数数组。它还包含非常有用的
Callee()
Data()
方法。如果函数是JavaScript对象的一个方法,那么我认为可以使用
Callee()
来获取调用该方法的对象的任何实例。然后,有用的状态信息可以存储在对象实例中。您还可以提供一个数据句柄,当向对象添加函数模板时,它可以通过“代码> Value*/Cuff>”指向任何C++对象。然后可以通过
data()
方法访问此特定于函数的数据句柄

下面是一个相当完整的示例,说明了我在问题中使用
v8::Arguments::Data()
所做的工作。希望这对任何想做类似事情的人都有用。如果你有一个你喜欢的替代策略(我相信有不止一种方法),请在另一个答案中添加它

#include <iostream>
#include <ostream>
#include <v8.h>

// add print() function to an object template
void add_print(v8::Handle<v8::ObjectTemplate>& ot, std::ostream* out)
{
  // add function template to ot
  ot->Set(v8::String::New("print"), v8::FunctionTemplate::New(
    // parameter 1 is the function callback (implemented here as a lambda)
    [](const v8::Arguments& args)->v8::Handle<v8::Value>
    {
      // recover our pointer to an std::ostream from the
      // function template's data handle
      v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data());
      std::ostream* out = static_cast<std::ostream*>(data->Value());

      // verify that we have the correct number of function arguments
      if ( args.Length() != 1 )
        return v8::ThrowException(v8::String::New("Too many arguments to print()."));

      // print the ascii representation of the argument to the output stream
      v8::String::AsciiValue ascii(args[0]);
      *out << *ascii << "\n";

      // like 'return void;' only in JavaScript
      return v8::Undefined();
    },

    // parameter 2 is the data handle with the pointer to an std::ostream
    v8::External::New(out)
  ));
}

int main()
{
  // create a stack-allocated handle scope
  v8::HandleScope handle_scope;

  // create a global template
  v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

  // add a print() function using std::cout to the global template
  add_print(global, &std::cout);

  // create a context
  v8::Persistent<v8::Context> context = v8::Context::New(nullptr, global);

  // enter the created context
  v8::Context::Scope context_scope(context);

  // create a string containing the JavaScript source code
  v8::Local<v8::String> source = v8::String::New("print('1 + 1 = ' + (1 + 1));");

  // compile the source code
  v8::Local<v8::Script> script = v8::Script::Compile(source);

  // run the script
  script->Run();

  // dispose of the persistent context
  context.Dispose();

  return 0;
}
#包括
#包括
#包括
//将print()函数添加到对象模板
无效添加打印(v8::Handle&ot,std::ostream*out)
{
//将函数模板添加到ot
ot->Set(v8::String::New(“打印”),v8::FunctionTemplate::New(
//参数1是函数回调(在这里作为lambda实现)
[](常量v8::参数和参数)->v8::句柄
{
//从中恢复指向std::ostream的指针
//函数模板的数据句柄
v8::Handle data=v8::Handle::Cast(args.data());
std::ostream*out=static_cast(数据->值());
//验证函数参数的数量是否正确
如果(参数长度()!=1)
返回v8::ThroweException(v8::String::New(“要打印的参数太多()”);
//将参数的ascii表示形式打印到输出流
v8::String::Ascivalue ascii(args[0]);
*出去
#include <iostream>
#include <ostream>
#include <v8.h>

// add print() function to an object template
void add_print(v8::Handle<v8::ObjectTemplate>& ot, std::ostream* out)
{
  // add function template to ot
  ot->Set(v8::String::New("print"), v8::FunctionTemplate::New(
    // parameter 1 is the function callback (implemented here as a lambda)
    [](const v8::Arguments& args)->v8::Handle<v8::Value>
    {
      // recover our pointer to an std::ostream from the
      // function template's data handle
      v8::Handle<v8::External> data = v8::Handle<v8::External>::Cast(args.Data());
      std::ostream* out = static_cast<std::ostream*>(data->Value());

      // verify that we have the correct number of function arguments
      if ( args.Length() != 1 )
        return v8::ThrowException(v8::String::New("Too many arguments to print()."));

      // print the ascii representation of the argument to the output stream
      v8::String::AsciiValue ascii(args[0]);
      *out << *ascii << "\n";

      // like 'return void;' only in JavaScript
      return v8::Undefined();
    },

    // parameter 2 is the data handle with the pointer to an std::ostream
    v8::External::New(out)
  ));
}

int main()
{
  // create a stack-allocated handle scope
  v8::HandleScope handle_scope;

  // create a global template
  v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

  // add a print() function using std::cout to the global template
  add_print(global, &std::cout);

  // create a context
  v8::Persistent<v8::Context> context = v8::Context::New(nullptr, global);

  // enter the created context
  v8::Context::Scope context_scope(context);

  // create a string containing the JavaScript source code
  v8::Local<v8::String> source = v8::String::New("print('1 + 1 = ' + (1 + 1));");

  // compile the source code
  v8::Local<v8::Script> script = v8::Script::Compile(source);

  // run the script
  script->Run();

  // dispose of the persistent context
  context.Dispose();

  return 0;
}