Estoy buscando escribir algunos enlaces de C a V8, por lo que tendré que averiguar el diseño de la memoria de los diversos tipos primitivos de JavaScript. ¿Hay alguna documentación sobre estos detalles en alguna parte?
No necesita conocer el diseño de tipos de datos para escribir enlaces C para V8. Nunca se accede realmente a los objetos directamente cuando trabaja con V8, sino a través de una API: solo la implementación de V8 sabe cómo se distribuyen. Por ejemplo, obtener una propiedad foo de un objeto o se ve así en C++:
v8::Handle<v8::Object> o; v8::Handle<v8::Object> v = o->Get(v8::String::NewFromUtf8(isolate, "foo")); Ahora, para envolver esto en C, solo necesita saber cómo representar y pasar v8::Handle<T> , luego puede escribir envoltorios como:
template<typename T> Handle<T> FromC(v8_handle_t h) { /* ... */ } template<typename T> v8_handle_t ToC(Handle<T> h) { /* ... */ } extern "C" v8_handle_t v8_object_get(v8_handle_t self, v8_handle_t key) { return ToC(FromC<Object>(self)->Get(FromC<Value>(key))); } Entonces, ¿qué hay dentro de v8::Handle<T> ? En realidad, es solo un puntero a una ranura que, a su vez, contiene un puntero real a un objeto V8 subyacente. Esta doble dirección indirecta existe para permitir que V8 GC rastree con precisión qué objetos están en uso en el código C++ y para permitirle mover estos objetos.
Entonces, en teoría, puede definir v8_handle_t como un puntero opaco y ordenarlo de esta manera:
typedef struct v8_object_pointer_t* v8_handle_t; // Opaque pointer static_assert(sizeof(v8_handle_t) == sizeof(Handle<Object>)) template<typename T> Handle<T> FromC(v8_handle_t h) { return *(Handle<T>*)&h; } template<typename T> v8_handle_t ToC(const Handle<T>& h) { return *(v8_handle_t*)&h; } Una complicación menor proviene de la gestión de la estructura denominada HandleScope que gestiona los Handle s. En la API de C++, se basa en el patrón RAII para administrar algo de almacenamiento de respaldo. La forma más sencilla de lidiar con esto probablemente sea:
typedef struct { void* a[3]; } v8_handle_scope_t; static_assert(sizeof(v8_handle_scope_t) == sizeof(HandleScope)) void v8_handle_scope_enter(v8_handle_scope_t* scope) { new(scope) HandleScope; } void v8_handle_scope_leave(v8_handle_scope_t* scope) { delete (HandleScope*)scope; }Con un uso cuidadosamente equilibrado en el código que necesita manejar ámbitos:
for (i = 0; i < N; i++) { v8_handle_scope_t scope; v8_handle_scope_enter(&scope); // action v8_handle_scope_leave(&scope); }Como su pregunta es sobre cómo escribir complementos V8 C ++ para Node.js, debe consultar el manual para nodeJs que tiene una guía razonablemente simple para escribir complementos ;
Si su pregunta es sobre cómo hacer subprocesos en segundo plano, hay complementos de nodejs que lo ayudan con eso, pero también lea esto para saber cómo escribirlo directamente.
Nunca debe intentar acceder a la memoria para V8 directamente, ya que la memoria y el objeto pueden moverse; use siempre las API.