I'm trying to write a Node.js module, using C++, that wraps and exposes some classes from libhdf5.
I'm currently interested in two classes from libhdf5. The first one is File
, and it opens an hdf5 file. The second one is Group
, and it represents groups within that file. You get Group objects from a File object.
I've written some code in which I create a File
object and attempt to get a Group
from it. I am trying to make my Node.js module as JavaScripty as possible, so I want to return the group using a callback. So, I am trying to code my module so that it's used like this:
var hdf5 = require('hdf5');
var file = new hdf5.File('/tmp/example.h5');
file.getGroup('foobar', function (err, group) { console.log(group); });
So, in the C++ code for my File
wrapper, I'd have a function that maps to the getGroup
function here, and it'd call the given anonymous function, passing in any errors as well as the new Group
object wrapper.
Given that this sounded to me like what the Node.js documentation shows to be a factory of wrapped objects, I have modeled my Group
code after the examples there.
So, I have my Group
wrapper coded up, but am stuck trying to instantiate it. I don't know enough yet to know how to stray away from using the v8 Arguments
class for function parameters. Because of that, I can't seem to be able to pass in some parameters that I need for my v8 persistent constructor function (because I am instantiating this from C++, and not from JS-land).
You are almost there. You don't need to pass Arguments
to Group::Instantiate
. Just pass what you need and use the constructor to create the new instance of Group
. For example:
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));
}
The method Group::New
does the rest of the construction work.
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();
}
In File::OpenGroup
you can do this:
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());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With