如何将封装的C++对象传递给Javascript回调函数?

10

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

我目前对libhdf5中的两个类感兴趣。第一个是 File ,它打开一个hdf5文件。第二个是 Group ,它表示该文件中的组。您可以从File对象中获取Group对象。

我编写了一些代码,其中创建了一个 File 对象并尝试从中获取一个 Group 。我希望使我的Node.js模块尽可能像JavaScript一样,因此我想使用回调返回组。因此,我正在编写我的模块,使其像这样使用:

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

因此,在我的File包装器的C++代码中,我会有一个函数映射到这里的getGroup函数,并调用给定的匿名函数,传递任何错误以及新的Group对象包装器。

鉴于这听起来像Node.js文档所显示的包装对象工厂,我已经根据那里的示例对我的Group代码进行了建模。

因此,我已经编写了我的Group包装器代码,但在尝试实例化它时卡住了。我还不足够了解如何避免使用v8 Arguments类作为函数参数。因此,我似乎无法传递一些我需要的参数给我的v8持久构造函数(因为我是从C++实例化它,而不是从JS-land)。


嗨,Ryan。你的repo链接都失效了,可能已经被删除了(这就是为什么要避免使用外部链接)。你能修复这个问题,以恢复它被提出时的状态吗?最好将代码放入问题本身,以避免再次发生此类情况。也许删除最后三段仍然能保持一些意义,你觉得呢? - halfer
1个回答

9

你已经快完成了。不需要把 Arguments 传给 Group::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));
}

方法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();
}

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());
}

这是否意味着您需要一个工厂方法(Group::Instantiate)来返回另一个类的实例? - ZachB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接