2016-09-27 37 views
-1

我想在基于oop的应用程序中使用v8,但我在代码中遇到了一些与v8对象范围有关的问题,当我在一个函数中编写所有代码时,我把一个类(甚至是一个名字空间)放入一些对象中会被损坏。在oop应用程序中使用V8引擎C++

此代码将工作没有任何错误:

//#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()

因为一些对象不能被访问或者它是空

#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

您正在为第二个代码中的每个函数调用明确地创建一个新的上下文,您认为这会对您做什么,原始的非隔离方法不会? – kfsone

+0

你可以请你减少你的代码墙,以提供一个[MVCE],再现你的问题。 –

+0

@kfsone这是我的错误复制代码,我编辑。 –

回答

0

你把v8::Local<...>对象类,但v8::Local的仅有内有效。只要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

相关问题