nodejs c++扩展 demo

编译语句:

node-gyp rebuild --target=2.0.5 --arch=x64 --dist-url=https://atom.io/download/electron --msvs_version=2015

依赖可以在 %USERPROFILE%\.node-gyp 目录下查找。
比如:%USERPROFILE%\.node-gyp\iojs-2.0.5\deps

src/node_demo_js.h

#ifndef __NODE_DEMO_JS_H__
#define __NODE_DEMO_JS_H__

#include "nan.h"

class NodeDemoJs : public Nan::ObjectWrap {
public:
    static void Init(v8::Local<v8::Object> exports);

private:
    explicit NodeDemoJs(std::string member, int status = 0);
    ~NodeDemoJs();

    static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
    static void GetStatus(const Nan::FunctionCallbackInfo<v8::Value>& info);
    static void AppInit(const Nan::FunctionCallbackInfo<v8::Value>& info);
    static void AppRun(const Nan::FunctionCallbackInfo<v8::Value>& info);
    static void AppCommand(const Nan::FunctionCallbackInfo<v8::Value>& info);
    static Nan::Persistent<v8::Function> constructor;

    void TestFunc1(std::string & parmas);
    void TestFunc2(int &status);
    std::string m_demo_member;
    int m_status;
};

#endif // __NODE_DEMO_JS_H__

src/node_demo_js.cpp

#include "node_demo_js.h"
#include "v8.h"
#include "node.h"
#include <thread>
#include <iostream>
#include <string>

#define EXPORT_OBJECT_NAME       "NodeDemoJs"
#define EXPORT_INF_GETSTATUS     "GetStatus"
#define EXPORT_INF_APPINIT       "AppInit"
#define EXPORT_INF_APPRUN        "AppRun"
#define EXPORT_INF_APPCOMMAND    "AppCommand"

Nan::Persistent<v8::Function> NodeDemoJs::constructor;

NodeDemoJs::NodeDemoJs(std::string name, int status)
    :m_demo_member(name), m_status(0) {
}

NodeDemoJs::~NodeDemoJs() {
}

void NodeDemoJs::Init(v8::Local<v8::Object> exports) {
    v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
    tpl->SetClassName(Nan::New(EXPORT_OBJECT_NAME).ToLocalChecked());
    tpl->InstanceTemplate()->SetInternalFieldCount(1);

    Nan::SetPrototypeMethod(tpl, EXPORT_INF_GETSTATUS, GetStatus);
    Nan::SetPrototypeMethod(tpl, EXPORT_INF_APPINIT, AppInit);
    Nan::SetPrototypeMethod(tpl, EXPORT_INF_APPRUN, AppRun);
    Nan::SetPrototypeMethod(tpl, EXPORT_INF_APPCOMMAND, AppCommand);

    constructor.Reset(tpl->GetFunction());
    exports->Set(Nan::New(EXPORT_OBJECT_NAME).ToLocalChecked(), tpl->GetFunction());
}

void NodeDemoJs::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    if (info.IsConstructCall()) {
        std::string name("");
        if (!info[0]->IsUndefined()) {
            v8::String::Utf8Value params1(info[0]->ToString());
            name = std::string(*params1);
        }
        if (name.length() == 0) {
            NodeDemoJs* obj = ObjectWrap::Unwrap<NodeDemoJs>(info.Holder());
            obj->m_status = -99;
            obj->Wrap(info.This());
            info.GetReturnValue().Set(info.This());

            std::cout << "NodeDemoJs New error: name is null. status: " << obj->m_status << std::endl;
            return;
        }

        int status = 0;
        if (!info[1]->IsUndefined()) {
            status = info[1]->Int32Value();
        }

        NodeDemoJs* obj = new NodeDemoJs(name, status);
        obj->m_status = 0;
        obj->Wrap(info.This());
        info.GetReturnValue().Set(info.This());

        std::cout << obj->m_demo_member << ": NodeDemoJs New Success.status:" << obj->m_status << std::endl;
    }
    else {
        const int argc = 1;
        v8::Local<v8::Value> argv[argc] = { info[0] };
        v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
        info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked());

        std::cout << ": NodeDemoJs ReNew Success.status: nvl" << std::endl;
    }
}

void NodeDemoJs::GetStatus(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    NodeDemoJs* obj = ObjectWrap::Unwrap<NodeDemoJs>(info.Holder());
    info.GetReturnValue().Set(Nan::New(obj->m_status));
}

void NodeDemoJs::AppInit(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    NodeDemoJs* obj = ObjectWrap::Unwrap<NodeDemoJs>(info.Holder());

    std::string name = obj->m_demo_member;
    int status = 2;
    obj->TestFunc2(status);
    std::cout << "TestFunc2(2) " << status << std::endl;

    obj->m_status = 1;
    info.GetReturnValue().Set(Nan::New(obj->m_status));

    std::cout << obj->m_demo_member << ": AppInit Success. status:" << obj->m_status << std::endl;
}

void NodeDemoJs::AppRun(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    NodeDemoJs* obj = ObjectWrap::Unwrap<NodeDemoJs>(info.Holder());

    obj->m_status = 2;
    info.GetReturnValue().Set(Nan::New(obj->m_status));

    std::cout << obj->m_demo_member << ": AppRun Success. status:" << obj->m_status << std::endl;
}

void NodeDemoJs::AppCommand(const Nan::FunctionCallbackInfo<v8::Value>& info) {
    NodeDemoJs* obj = ObjectWrap::Unwrap<NodeDemoJs>(info.Holder());
    v8::Isolate * isolate = info.GetIsolate();

    v8::Local<v8::String> value = info[0]->IsUndefined() ? v8::String::NewFromUtf8(isolate, std::to_string(3).c_str()) : info[0]->ToString();
    std::string params(*v8::String::Utf8Value(value));
    obj->m_status = 3;
    std::cout << params << obj->m_status << std::endl;

    info.GetReturnValue().Set(Nan::New(obj->m_status));
}

void NodeDemoJs::TestFunc1(std::string & parmas)
{
    std::cout << "NodeDemoJs::TestFunc1(" << parmas << ")" << std::endl;
}

void NodeDemoJs::TestFunc2(int &status)
{
    status *= 2;
    std::cout << "ststus: " << status << std::endl;
}

src/node_demo_js_main.cpp

#include "node_demo_js.h"

void InitAll(v8::Local<v8::Object> exports) {
    NodeDemoJs::Init(exports);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)

binding.gyp

{
  "targets": [
    {
      # 注意 target_name 的名字不能有-号
      "target_name": "node_demo_js",
      #"type": "shared_library",
      "sources": [ "src/node_demo_js.cpp",
                   "src/node_demo_js.h",
                   "src/node_demo_js_main.cpp"
                  ],
      'msbuild_toolset': 'v140',
      'include_dirs': [ 
        '../electron-deps/iojs-2.0.5/src',
        '../electron-deps/iojs-2.0.5/deps/uv/include',
        '../electron-deps/iojs-2.0.5/deps/nan',
        '../electron-deps/iojs-2.0.5/deps/v8/include'
      ],
      'link_settings': {
        'conditions': [
          ['OS=="win" and target_arch=="ia32"', {
            'libraries': [ '-l../../electron-deps/iojs-2.0.5/ia32/iojs' ],
          }],
          ['OS=="win" and target_arch=="x64"', {
            'libraries': [ '-l../../electron-deps/iojs-2.0.5/x64/iojs' ],
          }],
        ],
      },
    'conditions': [
      # 配合调试和发布,设置c++预编译宏
      ['target_arch=="x64"', {
        'defines': [
           'WIN32',
           '_ARCH=64',
        ],
      }],
      ['target_arch=="ia32"', {
        'defines': [
           'WIN32',
           '_ARCH=32',
        ],
      }],
      ],
      # msvs编译后处理
      'msvs_postbuild': r'copy /y "$(OutDir)$(TargetName)$(TargetExt)" "$(OutDir)..\..\bin\<(target_arch)\$(TargetName)$(TargetExt)"',
    },
  ],
}

猜你喜欢

转载自blog.csdn.net/longji/article/details/81277091