2016-06-03 3 views
2

V8에서 비동기 호출을 수행하는 방법을 알아 냈습니다. 나는 실행을하기 위해 노력하고있어 자바 스크립트 코드의 예는 다음과 같습니다V8 javascript 비동기 호출 방법

function test() 
{ 
    logMessage ('asynchronous call made!'); 
} 
saveFunc(test); 

saveFunc 기능은 스크립트가 실행 된 후 C++ 코드가 나중에 호출 할 때 사용하기 위해 테스트 기능을 저장하기로되어있다. 이것을 시도 할 때마다 나는 저장된 기능을 실행하려고 할 때 충돌이 발생합니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

아래 예제 코드를 모두 복사했습니다. 미리 감사드립니다.

예제 코드 :

// Copyright 2015 the V8 project authors. All rights reserved. 
// Use of this source code is governed by a BSD-style license that can be 
// found in the LICENSE file. 

#include <iostream> 
#include <string> 

#include "libplatform/libplatform.h" 
#include "v8.h" 

using namespace v8; 

Local<Context> context; 
v8::Local<v8::Function> savedFunc; 

class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 
public: 
    virtual void* Allocate(size_t length) { 
     void* data = AllocateUninitialized(length); 
     return data == NULL ? data : memset(data, 0, length); 
    } 
    virtual void* AllocateUninitialized(size_t length) { return malloc(length); } 
    virtual void Free(void* data, size_t) { free(data); } 
}; 

std::string parseV8Value(v8::Local<v8::Value> str) 
{ 
    if (str.IsEmpty() == true) 
     return (""); 

    v8::String::Utf8Value newStr(str); 

    return (*newStr); 
} 

void logMessage(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    std::string applicationSource = parseV8Value(args[0]); 
    std::cout << applicationSource << "\n"; 
} 

void getInput(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast (args[0]); 
    std::string input = ""; 

    std::cin >> input; 

    v8::Local<v8::Value> *args2 = new v8::Local<v8::Value>[1]; 
    args2[0] = v8::String::NewFromUtf8 (args.GetIsolate(), input.c_str()); 

    func->Call (context->Global(), 1, args2); 

    delete []args2; 
    args2 = NULL; 
} 

void saveFunc(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    savedFunc = v8::Local<v8::Function>::Cast(args[0]); 
} 

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. 
     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); 
     global->Set(v8::String::NewFromUtf8(isolate, "logMessage"), 
      v8::FunctionTemplate::New(isolate, logMessage)); 
     global->Set(v8::String::NewFromUtf8(isolate, "getInput"), 
      v8::FunctionTemplate::New(isolate, getInput)); 
     global->Set(v8::String::NewFromUtf8(isolate, "saveFunc"), 
      v8::FunctionTemplate::New(isolate, saveFunc)); 
     context = Context::New(isolate, NULL, global); 

     // 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, 
      "function test(){ logMessage ('asynchronous call made!'); }saveFunc(test);",, 
       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(); 

     v8::Local<v8::Value> *args = new v8::Local<v8::Value>[0]; 
     savedFunc->Call(context->Global(), 0, args); 

     delete []args; 
     args = NULL; 
    } 

    // Dispose the isolate and tear down V8. 
    isolate->Dispose(); 
    V8::Dispose(); 
    V8::ShutdownPlatform(); 
    delete platform; 
    return 0; 
} 
+0

나는 무엇을 하려는지 잘 모르겠습니다. 'save.get()'] (https://nodejs.org/api/process.html#process_process_nexttick_callback_arg)와 같은 일을하기로되어있는'saveFunc()'입니까? –

+0

로컬 핸들과 영구 핸들 간의 차이점을 이해해야합니다. https://developers.google.com/v8/embed#handles-and-garbage-collection – AnatolyS

+1

Congradulations - 대부분의 사람들을 이스케이프 처리하는 JavaScript의 기본 사항 중 하나를 알아 냈습니다. 동시성과 비동기 호출은 JavaScript에서 오지 않습니다. Chromium 또는 Node-Node와 같은 호스트 환경에서 랩핑되어 예를 들어 LibUV로 구동됩니다. –

답변

3

좋아, 그래서 당신은 saveFunc의 기능을 저장할 때 영구 핸들을 사용해야합니다. 또한, 컨텍스트 -> 글로벌에 액세스 할 때 HandleScope에 있음을 확인해야합니다. 수정 된 코드는 다음과 같습니다.

// Copyright 2015 the V8 project authors. All rights reserved. 
// Use of this source code is governed by a BSD-style license that can be 
// found in the LICENSE file. 

#include <iostream> 
#include <string> 

#include "libplatform/libplatform.h" 
#include "v8.h" 

using namespace v8; 

Isolate* isolate = NULL; 
Local<Context> context; 
v8::Persistent<v8::Function> *savedFunc = NULL; 

class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { 
public: 
    virtual void* Allocate(size_t length) { 
     void* data = AllocateUninitialized(length); 
     return data == NULL ? data : memset(data, 0, length); 
    } 
    virtual void* AllocateUninitialized(size_t length) { return malloc(length); } 
    virtual void Free(void* data, size_t) { free(data); } 
}; 

std::string parseV8Value(v8::Local<v8::Value> str) 
{ 
    if (str.IsEmpty() == true) 
     return (""); 

    v8::String::Utf8Value newStr(str); 

    return (*newStr); 
} 

void logMessage(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    std::string applicationSource = parseV8Value(args[0]); 
    std::cout << applicationSource << "\n"; 
} 

void getInput(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast (args[0]); 
    std::string input = ""; 

    std::cin >> input; 

    v8::Local<v8::Value> *args2 = new v8::Local<v8::Value>[1]; 
    args2[0] = v8::String::NewFromUtf8 (args.GetIsolate(), input.c_str()); 

    func->Call (context->Global(), 1, args2); 

    delete []args2; 
    args2 = NULL; 
} 

void saveFunc(const v8::FunctionCallbackInfo<v8::Value> &args) 
{ 
    v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(args[0]); 
    savedFunc = new v8::Persistent<v8::Function>(); 
    savedFunc->Reset(isolate, func); 
} 

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::New(create_params); 
    { 
     Isolate::Scope isolate_scope(isolate); 

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

     // Create a new context. 
     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); 
     global->Set(v8::String::NewFromUtf8(isolate, "logMessage"), 
      v8::FunctionTemplate::New(isolate, logMessage)); 
     global->Set(v8::String::NewFromUtf8(isolate, "getInput"), 
      v8::FunctionTemplate::New(isolate, getInput)); 
     global->Set(v8::String::NewFromUtf8(isolate, "saveFunc"), 
      v8::FunctionTemplate::New(isolate, saveFunc)); 
     context = Context::New(isolate, NULL, global); 

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

     // The "asynchronous" javascript call to make 
     Local<String> source = 
      String::NewFromUtf8(isolate, 
    "function test(){ logMessage ('asynchronous call made!'); }saveFunc(test);", 
       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(); 

     v8::Local<v8::Value> *args = new v8::Local<v8::Value>[0]; 
     v8::Local<v8::Value> recv = context->Global(); 
     v8::Local<v8::Function> func = savedFunc->Get(isolate); 
     func->Call (recv, 0, args); 

     delete savedFunc; 
     savedFunc = NULL; 

     delete []args; 
     args = NULL; 
    } 

    // Dispose the isolate and tear down V8. 
    isolate->Dispose(); 
    V8::Dispose(); 
    V8::ShutdownPlatform(); 
    delete platform; 
    return 0; 
}