Dear All,
I am a C developer quite new to v8 (I have limited c++ knowledge).
Sorry if I ask very basic questions.
I have a C application that need to execute some js code in different times preserving the same context.
My code looks like:
Header file
=========
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
typedef struct V8Engine V8Engine;
typedef struct V8Context V8Context;
typedef struct V8Value V8Value;
V8Engine* V8EngineInit (const char *path);
void V8EngineFree (V8Engine *engine);
V8Context* V8ContextCreate (V8Engine *engine);
void V8ContextFree (V8Context *context);
V8Value* V8ExecuteScript (V8Context *context, const char *script);
bool V8ValueIsError (V8Value *value);
#ifdef __cplusplus
}
#endif
#endif
C++ file
======
#include "libplatform/libplatform.h"
#include "v8.h"
#include "c8.h"
struct V8Engine {
std::unique_ptr<v8::Platform> platform;
v8::Isolate::CreateParams create_params;
v8::Isolate *isolate;
v8::Isolate::Scope *isolate_scope;
};
struct V8Context {
V8Engine *engine;
v8::Global<v8::Context> *context;
};
struct V8Value {
};
// MARK: -
extern "C" {
V8Engine* V8EngineInit (const char *path) {
V8Engine *engine = (V8Engine *)calloc(1, sizeof(V8Engine));
if (!engine) return nullptr;
// Initialize V8
v8::V8::InitializeICUDefaultLocation(path);
v8::V8::InitializeExternalStartupData(path);
engine->platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(engine->platform.get());
v8::V8::Initialize();
engine->create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
engine->isolate = v8::Isolate::New(engine->create_params);
engine->isolate_scope = new v8::Isolate::Scope(engine->isolate);
return engine;
}
void V8EngineFree (V8Engine *engine) {
if (engine == NULL) return;
if (engine->isolate_scope) {
delete engine->isolate_scope;
}
if (engine->isolate) {
engine->isolate->Dispose();
}
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
if (engine->create_params.array_buffer_allocator) {
delete engine->create_params.array_buffer_allocator;
}
engine->~V8Engine();
free(engine);
}
V8Context* V8ContextCreate (V8Engine *engine) {
V8Context *instance = (V8Context *)calloc(1, sizeof(V8Context));
if (!instance) return nullptr;
instance->engine = engine;
v8::Local<v8::Context> local_context = v8::Context::New(engine->isolate);
instance->context = new v8::Global<v8::Context>(engine->isolate, local_context);
return instance;
}
void V8ContextFree (V8Context *context) {
delete context->context;
context->~V8Context();
free(context);
}
V8Value* V8ExecuteScript (V8Context *instance, const char *script) {
// Create a stack-allocated handle scope
v8::HandleScope handle_scope(instance->engine->isolate);
// Enter the context for compiling and running the script
v8::Local<v8::Context> context(instance->context->Get(instance->engine->isolate));
v8::Context::Scope context_scope(context);
{
// Create a string containing the JavaScript source code
v8::Local<v8::String> source = v8::String::NewFromUtf8(instance->engine->isolate, script, v8::NewStringType::kNormal).ToLocalChecked();
// Compile the source code
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
// Convert the result to an UTF8 string and print it
v8::String::Utf8Value utf8(instance->engine->isolate, result);
printf("%s\n", *utf8);
}
return nullptr;
}
bool V8ValueIsError (V8Value *value) {
return false;
}
}
// main C file
==========
int main (int argc, char* argv[]) {
V8Engine *vm = V8EngineInit(argv[0]);
V8Context *context = V8ContextCreate(vm);
const char *script1 = " function js_add_elements(var1, var2) { \
var var3 = parseInt(var1) + parseInt(var2); \
var result = 'Addition of ' + var1 + ' and ' + var2 + ' results ' + var3; \
return result; \
};";
const char *script2 = "js_add_elements(2, 3);";
const char *script3 = "js_add_elements(4, 5);";
V8ExecuteScript(context, script1);
V8ExecuteScript(context, script2);
V8ExecuteScript(context, script3);
V8ContextFree(context);
V8EngineFree(vm);
}
When I run this code this error is printed on console:
#
# Fatal error in v8::HandleScope::CreateHandle()
# Cannot create a handle without a HandleScope
#
on the line
v8::Local<v8::Context> local_context = v8::Context::New(engine->isolate);
in
V8Context* V8ContextCreate (V8Engine *engine)
Please let me know what I am doing wrong (a fixed sample code would be extremely useful).
Thanks a lot,
Marco Bambini