如何将包装好的C++对象传递给Javascript回调?

Rya*_*yan 10 c++ v8 node.js

我正在尝试使用C++编写Node.js模块,该模块包装并公开libhdf5中的一些类.

我目前对libhdf5的两个课程很感兴趣.第一个是File,它打开一个hdf5文件.第二个是Group,它代表该文件中的组.您从File对象获取Group对象.

我写了一些代码,我在其中创建了一个File对象并试图从中获取一个对象Group.我试图使我的Node.js模块尽可能为JavaScripty,所以我想使用回调返回该组.所以,我正在尝试编写我的模块,以便它像这样使用:

var hdf5 = require('hdf5');
var file = new hdf5.File('/tmp/example.h5');
file.getGroup('foobar', function (err, group) { console.log(group); });
Run Code Online (Sandbox Code Playgroud)

所以,在我的File包装器的C++代码中,我有一个映射到getGroup函数的函数,它调用给定的匿名函数,传入任何错误以及新的Group对象包装器.

鉴于这听起来像Node.js文档显示为包装对象工厂,我Group在那里的示例之后建模了我的代码.

所以,我有我的Group包装编码,但我试图实例化它.我还不知道如何偏离使用v8 Arguments类的函数参数.因此,我似乎无法传递我的v8持久构造函数所需的一些参数(因为我从C++实例化,而不是从JS-land实例化).

Jan*_*ard 9

你快到了.你不需要传递ArgumentsGroup::Instantiate.只需传递您需要的内容并使用构造函数创建新的实例Group.例如:

Handle<Value> Group::Instantiate(const std::string& name) {
    HandleScope scope;

    Local<v8::Value> argv[1] = {
        Local<v8::Value>::New(String::New(name.c_str()))
    };

    return scope.Close(Constructor->NewInstance(1, argv));
}
Run Code Online (Sandbox Code Playgroud)

该方法Group::New完成剩余的施工工作.

Handle<Value> Group::New(const Arguments& args) {
    HandleScope scope;

    if (!args[0]->IsString()) {
        return ThrowException(Exception::TypeError(String::New("First argument must be a string")));
    }
    const std::string name(*(String::Utf8Value(args[0]->ToString())));
    Group * const group = new Group(name);
    bar->Wrap(args.This());

    return args.This();
}
Run Code Online (Sandbox Code Playgroud)

File::OpenGroup你可以这样做:

Handle<Value> File::OpenGroup (const Arguments& args) {
    HandleScope scope;

    if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsFunction()) {
        ThrowException(Exception::SyntaxError(String::New("expected name, callback")));
        return scope.Close(Undefined());
    }
    const std::string name(*(String::Utf8Value(args[0]->ToString())));
    Local<Function> callback = Local<Function>::Cast(args[1]);

    const unsigned argc = 2;
    Local<Value> argv[argc] = {
        Local<Value>::New(Null()),
        Local<Value>::New(Group::Instantiate(name))
    };
    callback->Call(Context::GetCurrent()->Global(), argc, argv);

    return scope.Close(Undefined());
}
Run Code Online (Sandbox Code Playgroud)