2016-09-27 10 views
-1

oopベースのアプリケーションでC++でv8を使用したいのですが、コード内にv8オブジェクトのスコープに関するいくつかの問題があります。私はクラス(または名前空間)にオブジェクトのいくつかが壊れてしまいます。oopアプリケーションでV8エンジンを使用する

このコードは、エラーのない作品は以下となります。

//#include "stdafx.h" 
#include <Windows.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <iostream> 

#include <v8.h> 
#include <libplatform.h> 


using namespace v8; 

Handle<v8::Object> g_global; 

// Reads a file into a v8 string. 
v8::Handle<v8::String> _ReadFile(const char* name) 
{ 
#pragma warning(disable : 4996) 
    FILE* file = fopen(name, "rb"); 
    if (file == NULL) return v8::Handle<v8::String>(); 

    fseek(file, 0, SEEK_END); 
    int size = ftell(file); 
    rewind(file); 

    char* chars = new char[size + 1]; 
    chars[size] = '\0'; 
    for (int i = 0; i < size;) 
    { 
     int read = fread(&chars[i], 1, size - i, file); 
     i += read; 
    } 
    fclose(file); 
    v8::Handle<v8::String> result = v8::String::NewFromUtf8(g_global->GetIsolate(), chars); 
    delete[] chars; 
    return result; 

} 




Handle<v8::Value> CallJSFunction(std::string funcName, Handle<Value> argList[], unsigned int argCount) { 


Handle<v8::Object> global = g_global; 
// Create value for the return of the JS function 
Handle<Value> js_result; 
// Grab JS function out of file 
Handle<v8::Value> value = global->Get(String::NewFromUtf8(global->GetIsolate(), funcName.c_str())); 
// Cast value to v8::Function 
Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); 
// Call function with all set values 
js_result = func->Call(global, argCount, argList); 
// Return value from function 
return js_result; 
} 

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


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

     g_global = context->Global(); 

     // Try to include this js file into current context 
     Local<String> source = _ReadFile(R"(somjsfile.js)"); 
     Local<Script> script = Script::Compile(context, source).ToLocalChecked(); 
     script->Run(); 

      // 
      // functionName is a valid js code inside somjsfile.js file i test it and it's ok. 
      // 
      Handle<Value> js_result = CallJSFunction("functionName", nullptr, 0); 
      String::Utf8Value utf8(js_result); 

      printf("%s\n", *utf8); 
     } 

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

しかし、私はこのようなクラス内のコードを置けば、私はCallJSFunction()を呼び出すことはできません。

いくつかのオブジェクトにアクセスすることはできませんので、またはそれはあなたがあなたのクラスでv8::Local<...>オブジェクトを入れているが、v8::Local年代はの範囲内でのみ有効ですヌル

#pragma once 
#include "Common.h" 

#include <v8.h> 
#include <libplatform.h> 

using namespace v8; 

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

class JSUtil 
{ 
private: 
    v8::Isolate   * m_Isolate; 
    v8::Handle<v8::Object> m_global; 
    v8::Local<v8::Context> m_Context; 
    v8::Platform*   m_platform; 
    std::string LoadFileAsString(const char* name) 
    { 
#pragma warning(disable : 4996) 
     FILE* file = fopen(name, "rb"); 
     if (file == nullptr) 
      return nullptr; 

     fseek(file, 0, SEEK_END); 
     int size = ftell(file); 
     rewind(file); 

     char* chars = new char[size + 1]; 
     chars[size] = '\0'; 
     for (int i = 0; i < size;) 
     { 
      int read = fread(&chars[i], 1, size - i, file); 
      i += read; 
     } 
     fclose(file); 
     std::string result = std::string(chars); 
     delete[] chars; 
     return result; 
    } 

    bool InitV8Engine() 
    { 
     std::string exepath = R"(fullpath_of_exename)"; 
     // Initialize V8. 
     v8::V8::InitializeICU(); 
     v8::V8::InitializeExternalStartupData(exepath.c_str()); 
     m_platform = v8::platform::CreateDefaultPlatform(); 
     v8::V8::InitializePlatform(m_platform); 
     v8::V8::Initialize(); 


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

     m_Isolate = v8::Isolate::New(create_params); 

     v8::Isolate::Scope isolate_scope(m_Isolate); 
     // Create a stack-allocated handle scope. 
     v8::HandleScope handle_scope(m_Isolate); 
     // Create a new context. 
     m_Context = v8::Context::New(m_Isolate); 
     // Enter the context for compiling and running the hello world script. 
     v8::Context::Scope context_scope(m_Context); 


     IncludeJSFile(m_Context->Global()); 
     return true; 
    } 

    bool Shutdown() 
    { 
     // Dispose the isolate and tear down V8. 
     m_Isolate->Dispose(); 
     V8::Dispose(); 
     V8::ShutdownPlatform(); 
     delete m_platform; 
    } 
    bool IncludeJSFile(v8::Handle<v8::Object> global) 
    { 
     // 
     // Try to include this js file into current context 
     // 
     // Create a string containing the JavaScript source code. 
     std::string FileBuff = LoadFileAsString(R"(somjsfile.js)"); 
     v8::Local<v8::String> source = v8::String::NewFromUtf8(global->GetIsolate(), FileBuff.c_str()); 
     // Compile the source code. 
     v8::Local<v8::Script> script = v8::Script::Compile(m_Context, source).ToLocalChecked(); 
     // Run the script to get the result. 
     script->Run(); 

     return true; 
    } 

    v8::Handle<v8::Value> CallJSFunction(std::string funcName, v8::Handle<v8::Value> argList[], unsigned int argCount) 
    { 
      v8::Handle<v8::Object> global = m_global; 
// Create value for the return of the JS function 
v8::Handle<v8::Value> js_result; 

v8::Local<v8::String> tmp = v8::String::NewFromUtf8(global->GetIsolate(), funcName.c_str()); 
// Grab JS function out of file 
v8::Handle<v8::Value> value = global->Get(tmp); 
// Cast value to v8::Function 
v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value); 
// Call function with all set values 
js_result = func->Call(global, argCount, argList); 
// Return value from function 
return js_result; 
    } 
public: 
    JSUtil() 
    { 
     InitV8Engine(); 
    } 

    ~JSUtil() 
    { 
     Shutdown(); 
    } 
}; 
+0

2番目のコードでは、すべての関数呼び出しに対して新しいコンテキストを明示的に作成していますが、元の分離していないアプローチはそうではないと思いますか? – kfsone

+0

問題を再現する[MVCE]を提供するために、コードの壁を小さくしてください。 –

+0

@kfsoneそれは私のコピーコードの間違いだった、私はそれを編集する。 –

答えて

0

です。 HandleScopeがなくなるとすぐにLocalさんのことが分かります。

代わりに、オブジェクトを長期間保存したい場合は、v8::Global<...>にする必要があります。これらはガベージコレクタによって更新されているので、コストが高くなります。そのため、すべてがグローバルではありません。

グローバルの作成:

v8::Global<v8::Value> my_global(isolate, my_local); 

が戻ってそれから地元を取得するには:

v8::Local<v8::Value> my_local = my_global.Get(isolate); 

一つのことに注意することは、あなたのようにそれらに対処する必要がありますので、グローバルには、移動のみですstd::unique_ptrとなります。