2012-04-26 13 views
10

Bare ze mną, jak to wyjaśnię.Jak przekazać zawinięty obiekt C++ do wywołania zwrotnego JavaScript?

Próbuję napisać moduł Node.js, używając C++, który owija i odsłania niektóre klasy od libhdf5.

Obecnie jestem zainteresowany dwiema klasami z libhdf5. Pierwszy to File i otwiera plik hdf5. Drugi to Group i reprezentuje grupy w tym pliku. Otrzymujesz obiekty grupy z obiektu File.

Napisałem kod, w którym utworzę obiekt File i spróbuję pobrać z niego Group. Staram się, aby mój moduł Node.js był jak najbardziej przekonwertowany, więc chcę zwrócić grupę za pomocą wywołania zwrotnego. Więc staram się kod Mój moduł tak, że jest on wykorzystywany tak:

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

więc w kodu C++ dla mojego File owijki, musiałbym funkcję, która mapuje do funkcji getGroup tutaj, i to "dzwoń do podanej anonimowej funkcji, przekazując wszelkie błędy, a także nową obwolutę obiektu Group.

Biorąc pod uwagę, że brzmiało to tak, jak dokumentacja Node.js pokazuje, że jest to factory of wrapped objects, zamodelowałem mój kod Group po tamtejszych przykładach.

Moje opakowanie Group jest zakodowane, ale utknąłem próbując go utworzyć. Nie wiem jeszcze wystarczająco dużo, aby wiedzieć, jak odejść od korzystania z klasy v8 Arguments dla parametrów funkcji. Z tego powodu nie mogę wydawać się w stanie przekazać niektórych parametrów, których potrzebuję do mojej funkcji konstruktora trwałego v8 (ponieważ tworzę instancję z C++, a nie z JS-land).

Czy ktoś mógłby rzucić okiem na my code for libhdf5 i dać mi wskazówkę, jak to osiągnąć? Czuję, że jestem prawie na miejscu, ale po prostu coś mi brakuje.

Oto moja Group wrapper, z funkcją konstruktor podświetlone: ​​https://github.com/ryancole/node-hdf5/blob/master/src/h5_group.cc#L57-72

Oto moja File wrapper, z linia hightlighted gdzie będzie trzeba przekazać w moich parametrów, jako argumenty (lub cokolwiek to jest, że muszę to zmienić, aby to zadziałało: https://github.com/ryancole/node-hdf5/blob/master/src/h5_file.cc#L110

góry dzięki, i dzięki za czytanie tego tekstu ścianę :)

Odpowiedz

9

Jesteś prawie tam.. Nie musisz przekazywać Arguments do Group::Instantiate. Wystarczy przekazać to, czego potrzebujesz i użyć konstruktora, aby utworzyć nowe wystąpienie Group. Na przykład:

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

Resztę prac wykona metoda 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(); 
} 

W File::OpenGroup można to zrobić:

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

HTH

+0

Czy to znaczy, że trzeba metodę fabryczną ('Grupa :: Instantiate'), aby powrócić instancję innej klasy ? – ZachB

Powiązane problemy