10

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).

1
  • Hi Ryan. The links to your repo are all dead, presumably it has been deleted (this is why external links are discouraged). Would you repair this question in order to restore it how it was when it was asked? Ideally the code would be brought into the question itself, to avoid this happening again. It might be OK to delete the last three paragraphs and still maintain some meaning, what do you think? Commented Apr 26, 2018 at 9:50

1 Answer 1

9

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());
}
Sign up to request clarification or add additional context in comments.

1 Comment

Is that to say that you need a factory method (Group::Instantiate) to return an instance of another class?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.