2016-05-23 3 views
1

Возможно, это глупый вопрос (Я новичок в C++, просто хотел использовать его в качестве библиотеки для Android), но я не могу запустить оценку некоторых JS несколько раз.Как выполнить оценку V8 несколько раз?

Я начал с "hello world" учебник. Но тогда я хотел простую вещь, повторно запустить основной (просто обернуть содержание учебника кода в функции и запустить его дважды в новой пустой основной

Это то, что я получил:.

# 
# Fatal error in ../src/isolate.cc, line 1868 
# Check failed: thread_data_table_. 
# 

==== C stack trace =============================== 

1: 0xa890b9 
2: 0x6a22fc 
3: 0x42694f 
4: 0x405f66 
5: 0x405ec7 
6: __libc_start_main 
7: 0x405dc9 
Illegal instruction (core dumped) 

Это АМСВО после создание нового изолята

Isolate* isolate = Isolate::New(create_params); 

Ну, что я должен делать? Могу ли я с помощью неправильно конструкт или так? должен ли я закрыть/удалить/осветления нечто большее?

В увеличенном виде я просто хочу оценить функцию, которая может запускаться несколько раз, а кроме того, также запускать несколько jip-snipets в том же контексте (как разбить эту функцию?).

Любая идея?


UPDATE:

Ok, позволяет сказать, что основной можно разделить на три логические части:

инициализации

int main(int argc, char* argv[]) { 
// Initialize V8. 
V8::InitializeICU(); 
V8::InitializeExternalStartupData(argv[0]); 
Platform* platform = platform::CreateDefaultPlatform(); 
V8::InitializePlatform(platform); 
V8::Initialize(); 

// Create a new Isolate and make it the current one. 
ArrayBufferAllocator allocator; 
Isolate::CreateParams create_params; 
create_params.array_buffer_allocator = &allocator; 

оценка

Isolate* isolate = Isolate::New(create_params); 
{ 
Isolate::Scope isolate_scope(isolate); 

// Create a stack-allocated handle scope. 
HandleScope handle_scope(isolate); 

// Create a new context. 
Local<Context> context = Context::New(isolate); 

// Enter the context for compiling and running the hello world script. 
Context::Scope context_scope(context); 

// Create a string containing the JavaScript source code. 
Local<String> source = 
    String::NewFromUtf8(isolate, "'Hello' + ', World!'", 
         NewStringType::kNormal).ToLocalChecked(); 

// Compile the source code. 
Local<Script> script = Script::Compile(context, source).ToLocalChecked(); 

// Run the script to get the result. 
Local<Value> result = script->Run(context).ToLocalChecked(); 

// Convert the result to an UTF8 string and print it. 
String::Utf8Value utf8(result); 
printf("%s\n", *utf8); 
} 
isolate->Dispose(); 

и чистый

// Dispose and tear down V8. 
V8::Dispose(); 
V8::ShutdownPlatform(); 
delete platform; 
return 0; 

Теперь, как я уже говорил, если я бегу главный состоит из init-> evaluation-> чистый дважды, это значит аннулирование-> оценка-> clean-> init-> оценка-> чистый, тогда возникает ошибка. Я выяснил, что если я извлечу Оценка часть в отдельную функцию Я могу запустить ее несколько раз, например. в инициализации -> (оценка) {2} -> чистый

Это, как она должна работать? Следующий шаг - разделить эту основную на отдельную функцию дерева, которая означает, что у меня должен быть статический член с платформой? Может ли это вызвать утечку?

ПРИМЕЧАНИЕ:, что я хочу запустить его из Android, что означает, например, щелкните в пользовательском интерфейсе, распространите источник js на C через JNI, а затем вызовите C++ V8, который уже инициализирован или нет. гм?

Предпочитаемый способ - иметь «черный ящик», но если мне нужно удерживать платформу, пусть будет так. Возможно, это может быть и быстрее без повторной инициализации V8, верно?


UPDATE 2:

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

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

:(

+0

Я думаю, что нам нужно немного больше, чем просто контекст 'изолята :: new'. – MSalters

+0

@MSalters см. Обновление :) – ThinkDeep

+0

Привет @ThinkDeep Я сталкиваюсь с той же проблемой, пожалуйста, вы можете вставить полный код? Благодарю. –

ответ

1

Мое предположение, как я ввел в Update1 было правильным. Эта часть работает хорошо.

По UPDATE2 Я расщепляется оценка часть надвое.

Сначала для инициализации изоляции и контекста:

mIsolate = Isolate::New(mCreate_params); 
Isolate::Scope isolate_scope(mIsolate); 
{ 
    // Create a stack-allocated handle scope. 
    HandleScope handle_scope(mIsolate); 

    v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(mIsolate); 
    // Bind the global 'print' function to the C++ Print callback. 
    global->Set(v8::String::NewFromUtf8(mIsolate, "print"), v8::FunctionTemplate::New(mIsolate, Print)); 

    // Create a new context. 
    mContext = Context::New(mIsolate, NULL, global); 
    Persistent<Context, CopyablePersistentTraits<Context>> persistent(mIsolate, mContext); 
    mContext_persistent = persistent; 
} 

и второй, который будет работать JS в одном контексте:

Isolate::Scope isolate_scope(mIsolate); 
{ 
    HandleScope handle_scope(mIsolate); 
    mContext = Local<Context>::New(mIsolate, mContext_persistent); 
    // Enter the context for compiling and running the hello world script. 
    Context::Scope context_scope(mContext); 
    { 
     // Create a string containing the JavaScript source code. 
     Local<String> source = 
      String::NewFromUtf8(mIsolate, js_source, NewStringType::kNormal).ToLocalChecked(); 

     // Compile the source code. 
     Local<Script> script = Script::Compile(mContext, source).ToLocalChecked(); 

     TryCatch trycatch(mIsolate); 

     // Run the script to get the result. 
     v8::Local<v8::Value> result; 
     if(!script->Run(mContext).ToLocal(&result)){ 
      v8::String::Utf8Value exception_str(trycatch.Exception()); 
      dprint(*exception_str); 
     }else{ 
      if(!result->IsUndefined()){ 
       String::Utf8Value utf8(result); 
       dprint(*utf8); 
      } 
     } 
    } 
} 

Ну код работает очень хорошо на Linux, но я до сих пор есть некоторые проблемы, когда я пытаюсь запустить первую часть во второй раз (создать новый контекст) на андроид:

A/art: art/runtime/thread.cc:986] pthread_getschedparam failed for DumpState: No such process 
A/art: art/runtime/base/mutex.cc:485] Unexpected state_ 0 in unlock for logging lock 

Но это другой вопрос, на мой взгляд. Мир.

+0

Похоже, что проблема связана с особенностями платформы Android, поскольку она возникает, например. с armeabi, а не x86. – ThinkDeep

0

Вы инициализировали v8 более одного раза?

v8::V8::Initialize() Этот метод следует вызывать один раз в процессе.

глубоко в исходный файл проекта "v8/src/v8.cc", вы найдете доказательства

bool V8::Initialize() { 
    InitializeOncePerProcess(); 
    return true; 
}