2016-12-18 2 views
4

При использовании V8 в качестве механизма создания сценариев я выставляю Javascript функцию C++ под названием construct_with_ec6_syntax. Эта функция при вызове должна просто вернуть экземпляр some_ec6_class.Как вернуть новый экземпляр класса «V8» класса V8 из C++?

функция

Это C++ в основном должна сделать следующее эквивалент Javascript:

return new some_ec6_class(111, 222); 

Этот класс будет определен в Javascript следующим с EC6 синтаксис:

class some_ec6_class 
{ 
    constructor(x, y) { 
     this.result = x + y; 
    } 
} 

Моя цель заключается в запуске следующие в Javascript ...

var the_instance = construct_with_ec6_syntax(111, 222); 
the_instance.result ; // .. and get 333 here. 

Моя текущая реализация для функции C++ заключается в следующем:

void construct_with_ec6_syntax(const FunctionCallbackInfo<Value>& args) { 
    Handle<Object> global = args.GetIsolate()->GetCurrentContext()->Global(); 
    std::string newvecfunc = "some_ec6_class"; 
    Handle<Value> value = global->Get(String::NewFromUtf8(args.GetIsolate(), newvecfunc.c_str(), String::kNormalString, newvecfunc.length())); 
    Local<Value> result; 
    if (value->IsFunction()) { 
     Handle<Function> func = Handle<Function>::Cast(value); 
     Handle<Value> args2[2]; 
     args2[0] = Number::New(args.GetIsolate(), 111); 
     args2[1] = Number::New(args.GetIsolate(), 222); 
     result = func->CallAsConstructor(args.GetIsolate()->GetCurrentContext(), 2, args2).ToLocalChecked(); 
    } 
    args.GetReturnValue().Set(result); 
} 

Выполнение этой функции из JavaScript, имеет его вернуть undefined! Вместо объекта, которого я ожидаю. Как указал мне xaxxon, это потому, что value->IsFunction() возвращает false, но value->IsUndefined() возвращает true. Если бы я определил класс, используя с не синтаксиса EC6, выше функция делает возвращает экземпляр ..

function some_non_ec6_class(x, y) // this guy would work with the above function 
{ 
    this.result = x + y; 
} 

Так что я немного запутался! Должен ли я как-то быть более конкретным, например, сначала получить функцию constructor от объекта, а затем вызвать CallAsConstructor?

Любые подсказки оцениваются!

(Этот вопрос похож на Calling a v8 javascript function from c++ with an argument но отличается.)

Я использую V8 проверку от 22 октября 2016 года Полный тестовый:

https://gist.github.com/rayburgemeestre/c0abd528f6f67edbfe686d484c45ddbb

Незначительное обновление :

Как вы можете видеть в комментариях, я также рассмотрел более конкретный случай ING «выборки» класс из контекста здесь: https://gist.github.com/rayburgemeestre/df6193d532c7b7908fe27c89799bfa3a

Также я отправил в список рассылки v8-пользователей: https://groups.google.com/forum/#!topic/v8-users/Hj2j4rJMwBw

+0

Пожалуйста, обновите свой вопрос, чтобы кратко изложить свой текущий вопрос , так как ответов на него пока нет. Нам не нужно знать ваш процесс, чтобы добраться до того, где вы сейчас находитесь. Или, если вам больше не нужна помощь, просто удалите вопрос вообще. – xaxxon

+0

@xaxxon Да, мне все еще нужна помощь, я удалил часть процесса –

+0

. Кажется, вы не слишком много проверяете ошибки. Возвращает ли значение if (value-> IsFunction()) значение true? Если это никогда не будет выполняться, это объяснит ваше возвращаемое значение. – xaxxon

ответ

2

class является способ создания переменной в JavaScript, похожий на let. Переменные, созданные с помощью class, являются блочными областями и не создают глобальных свойств (опять же, аналогично let).Therefor он не доступен в context.global как функции:

http://exploringjs.com/es6/ch_variables.html

function Complete Block Yes 

class  No   Block No 

Вы должны явно создать глобальную переменную для вашего кода для работы:

some_es6_class = class{}; 

или явно передать в объект класса для вашей функции C++ после создания его с помощью синтаксиса «традиционный es6»:

class some_es6_class{}; 
some_native_function(some_es6_class); 

Редактирование: Я сделал еще несколько копаний, и я верю, что объект контекста имеет LexicalEnvironment, который совместно используется через его script, но отличается от глобального объекта. Когда имя просматривается, оно пересекает родительскую иерархию LexicalEnvironments, ища имя. Эти лексические среды не отображаются через API (и могут отсутствовать на самом деле), они являются конструкцией, используемой спецификацией JS для определения поведения, а не обязательной частью реализации).

+0

Прежде всего спасибо за кучу, я думаю, теперь понимаю, почему я не мог ссылаться на класс, и всякий раз, когда я пытался создать экземпляр на C++, я бы просто получил новый объект с тем же именем :) Первый подход, создающий глобальную переменную для класса, работает для меня и более эффективен, чем текущее обходное решение, которое я использовал до сих пор (с использованием заводской функции). –

+0

@ RayBurgemeestre рад, что мы поняли, что выяснили, и я довольно многому научился в процессе. – xaxxon

Смежные вопросы