Подтвердить что ты не робот

Как вызвать код С++ из Node.js?

В настоящее время я разрабатываю симулятор, который работает на сервере и должен отображать данные в браузере.

Для обслуживания файлов, общения и т.д. я хотел бы использовать Node.js. Но я не уверен, что он будет работать так же хорошо, как я бы хотел, чтобы он работал в вычислительном отделе, поэтому я хотел бы разработать часть моделирования на С++.

Симуляция разделена на отдельные "миры", которые начинаются с некоторых начальных параметров.

Каков наилучший способ сделать это?

4b9b3361

Ответ 1

Ну, V8 позволяет вызывать код С++ из JavaScript.

Итак, у вас может быть 3 части вашего кода:

  • Обычный С++, не подозревающий о node.js и V8. Это будет где World.
  • Клей node.js/V8-С++ код, позволяющий JS "видеть" части вашего класса World.
  • Нормальный код JavaScript, который связывается со стороной С++ с помощью слоя "glue"

Во-первых, понять, как общаются V8 и С++. Google предоставляет руководство для этого: https://developers.google.com/v8/embed

Затем вам понадобится node.js конкретный клей. См. http://www.slideshare.net/nsm.nikhil/writing-native-bindings-to-nodejs-in-c и http://syskall.com/how-to-write-your-own-native-nodejs-extension

Из приведенной выше ссылки на слайд-шоу:

#include <v8.h>
#include <node.h>

using namespace v8;

extern "C" {
   static void init(Handle<Object> target) {}
   NODE_MODULE(module_name, init)
}

Мы можем расширить это в нечто более близкое к тому, что вы хотите:

ЦСИ/world.h

#ifndef WORLD_H_
#define WORLD_H_

class World {
    public:
        void update();
};

extern World MyWorld;

#endif

ЦСИ/world.cpp

#include "world.h"
#include <iostream>

using std::cout;
using std::endl;

World MyWorld;

void World::update() {
    cout << "Updating World" << endl;
}

ЦСИ/bind.cpp

#include <v8.h>
#include <node.h>
#include "world.h"

using namespace v8;

static Handle<Value> UpdateBinding(const Arguments& args) {
    HandleScope scope;

    MyWorld.update();

    return Undefined();
}

static Persistent<FunctionTemplate> updateFunction;

extern "C" {
   static void init(Handle<Object> obj) {
      v8::HandleScope scope;

        Local<FunctionTemplate> updateTemplate = FunctionTemplate::New(UpdateBinding);

        updateFunction = v8::Persistent<FunctionTemplate>::New(updateTemplate);

      obj->Set(String::NewSymbol("update"), updateFunction->GetFunction());
   }

   NODE_MODULE(world, init)
}

DEMO/demo.js

var world = require('../build/Release/world.node');
world.update();

WScript

def set_options(opt):
  opt.tool_options("compiler_cxx")

def configure(conf):
  conf.check_tool("compiler_cxx")
  conf.check_tool("node_addon")

def build(bld):
  obj = bld.new_task_gen("cxx", "shlib", "node_addon") 
  obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE", "-Wall"]
  # This is the name of our extension.
  obj.target = "world"
  obj.source = "src/world.cpp src/bind.cpp"
  obj.uselib = []

В оболочке Linux некоторые настройки:

node-waf configure

Чтобы создать, запустите:

node-waf

Чтобы проверить:

node demo/demo.js

Вывод:

Updating World