Как передать завернутый объект С++ в обратный вызов Javascript?

Горе со мной, как я это объясняю.

Я пытаюсь написать модуль Node.js, используя С++, который обертывает и предоставляет некоторые классы из libhdf5.

В настоящее время меня интересуют два класса из libhdf5. Первый - File, и он открывает файл hdf5. Второй - Group, и он представляет группы внутри этого файла. Вы получаете объекты Group из объекта File.

Я написал код, в котором я создаю объект 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); });

Итак, в коде С++ для моей оболочки File у меня была бы функция, которая отображается здесь в функции getGroup, и она вызывала бы данную анонимную функцию, передавая любые ошибки, а также новая обтекающая оболочка Group.

Учитывая, что это звучит для меня так, как выглядит документация Node.js как factory обернутых объектов, у меня есть смоделировал мой код Group после примеров там.

Итак, у меня есть оболочка Group, закодированная, но я пытаюсь создать экземпляр. Я пока не знаю достаточно, чтобы знать, как отклониться от использования класса v8 Arguments для параметров функции. Из-за этого я, похоже, не могу передать некоторые параметры, которые мне нужны для моей постоянной функции конструктора v8 (потому что я создаю это из С++, а не из JS-land).

Кто-нибудь, пожалуйста, взгляните на мой код для libhdf5 и дайте мне указатель на то, как этого добиться? Я чувствую, что я почти там, но что я просто что-то пропустил.

Вот моя оболочка Group, с выделенной функцией конструктора: https://github.com/ryancole/node-hdf5/blob/master/src/h5_group.cc#L57-72

Вот моя обертка File, с строкой hightlighted, где мне нужно будет передать мои параметры, как Аргументы (или что бы это ни было, что мне нужно изменить это, чтобы это работало: https://github.com/ryancole/node-hdf5/blob/master/src/h5_file.cc#L110

Спасибо заранее, и спасибо за чтение этой стены текста.:)

Ответ 1

Ты почти там. Вам не нужно передавать 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());
}

НТН