Nodejs C++扩展,求教

Nodejs C++扩展,求教

定义了一个类,包括类的几个属性,还有几个方法,然后就是几个单独的方法,在引入v8.h,node.h之后要把原来的C++程序写成官方要求的那个格式,本人没学过C++,只能看懂一部分,求推介好的教程,或者传授一下经验,谢谢

12 回复

当然可以!在Node.js中创建C++扩展可以帮助你利用C++的高性能来优化某些计算密集型任务。下面我将提供一个简单的示例,帮助你理解如何将C++代码集成到Node.js中。

示例:创建一个简单的Node.js C++扩展

假设我们有一个简单的C++类,它包含一些属性和方法。我们将使用Node.js的N-API(Node.js的API接口)来创建这个扩展。

1. 创建C++源文件

首先,创建一个名为myaddon.cc的文件,并编写以下代码:

#include <napi.h>

class MyClass : public Napi::ObjectWrap<MyClass> {
public:
    MyClass(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyClass>(info) {}

    static Napi::FunctionReference constructor;

    Napi::Value getName(const Napi::CallbackInfo& info);
    void setName(const Napi::CallbackInfo& info, const Napi::Value& value);
};

// 初始化构造函数引用
Napi::FunctionReference MyClass::constructor;

Napi::Object MyClass::Init(Napi::Env env, Napi::Object exports) {
    Napi::HandleScope scope(env);

    // 创建构造函数模板
    Napi::FunctionTemplate ctor = Napi::FunctionTemplate::New(env, MyClass::New);
    ctor->SetClassName(Napi::String::New(env, "MyClass"));
    ctor->InstanceTemplate()->SetInternalFieldCount(1);

    // 添加方法
    ctor->InstanceTemplate()->Set(Napi::Symbol::WellKnown(env, "toStringTag"), Napi::String::New(env, "MyClass"));

    // 设置静态属性
    MyClass::constructor = Napi::Persistent(ctor->GetFunction());
    MyClass::constructor.SuppressDestruct();

    // 导出构造函数
    exports.Set("MyClass", MyClass::constructor.Value());

    return exports;
}

Napi::Object MyClass::New(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    if (info.Length() == 0 || !info[0].IsString()) {
        Napi::TypeError::New(env, "Expected a string").ThrowAsJavaScriptException();
    }
    MyClass* obj = new MyClass(info);
    obj->SetName(info[0].As<Napi::String>());
    obj->Wrap(info.This());
    return info.This();
}

Napi::Value MyClass::getName(const Napi::CallbackInfo& info) {
    Napi::Env env = info.Env();
    return Napi::String::New(env, this->name);
}

void MyClass::setName(const Napi::CallbackInfo& info, const Napi::Value& value) {
    if (!value.IsString()) {
        Napi::TypeError::New(info.Env(), "Expected a string").ThrowAsJavaScriptException();
    }
    this->name = value.As<Napi::String>();
}

Napi::Object InitModule(Napi::Env env, Napi::Object exports) {
    MyClass::Init(env, exports);
    return exports;
}

NODE_API_MODULE(addon, InitModule)

2. 编译C++源文件

为了编译上述代码,你需要安装node-gyp工具。你可以使用npm来安装它:

npm install -g node-gyp

然后,创建一个binding.gyp文件来指定编译选项:

{
  "targets": [
    {
      "target_name": "myaddon",
      "sources": [ "myaddon.cc" ]
    }
  ]
}

最后,运行以下命令来编译:

node-gyp configure build

3. 使用C++扩展

现在,你可以在Node.js中使用这个C++扩展了:

const addon = require('./build/Release/myaddon');

const myObj = new addon.MyClass('Hello');
console.log(myObj.getName()); // 输出: Hello

myObj.setName('World');
console.log(myObj.getName()); // 输出: World

通过这种方式,你可以将C++代码与Node.js无缝集成,并利用C++的性能优势。希望这个示例对你有所帮助!


我最近也在摸索着V8引擎,我自己C++基础也就那么点,但是摸索底层实现的,感觉好有意思。:) 同时感谢一楼提供的资料。:)

看下 nan.h

这边要做的是把C++实现的一个抠人像的算法,嵌入到opencv这个模块中

绑定到Matrix对象上,可以直接调用的,其中C++程序内部还要调用多个函数

以前写过c++扩展,感觉还挺简单的,但是似乎对不同版本需要兼容,大概是使用nan来兼容吧。 这个是之前写过的一篇文章,不知道是不是对你有帮助。http://aszxqw.com/work/2014/02/22/nodejs-cpp-addon-nodejieba.html

本人没学过C++…

主要是我也没有学过C++,更别提Node v8什么滴

很多的案例什么的都是“Hello,world”,能搞懂,但是去项目里弄,根本无从下手呀

对于Node.js的C++扩展开发,你可以参考以下步骤进行。首先,你需要确保你的环境已经配置好,包括安装node-gyp等工具。

示例代码

假设我们有一个简单的C++类,包含一个属性(比如整型变量)和一些方法:

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

class MyCppClass {
public:
    int myValue;

    void add(int a, int b, v8::Local<v8::Function> cb) {
        int sum = a + b;
        v8::Local<v8::Value> argv[1] = { v8::Integer::New(v8::Isolate::GetCurrent(), sum) };
        cb->Call(v8::Null(), 1, argv);
    }
};

void Initialize(v8::Local<v8::Object> exports) {
    MyCppClass* obj = new MyCppClass();
    obj->myValue = 5;

    // 将对象绑定到JavaScript
    v8::Persistent<v8::External> persistent;
    persistent.Reset(exports->GetIsolate(), v8::External::New(exports->GetIsolate(), obj));
    exports->Set(v8::String::NewFromUtf8(exports->GetIsolate(), "myCppObject"), v8::External::New(exports->GetIsolate(), obj));

    // 定义一个JS函数,可以调用C++中的方法
    v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(exports->GetIsolate(), Add);
    tpl->SetClassName(v8::String::NewFromUtf8(exports->GetIsolate(), "MyCppClass"));
    tpl->InstanceTemplate()->SetInternalFieldCount(1); // 设置内部字段数量
    NODE_SET_PROTOTYPE_METHOD(tpl, "add", Add);

    // 导出对象
    exports->Set(v8::String::NewFromUtf8(exports->GetIsolate(), "CppClass"), tpl->GetFunction());
}

NODE_MODULE(addon, Initialize)

// JavaScript调用的C++函数
void Add(const v8::FunctionCallbackInfo<v8::Value>& args) {
    Isolate* isolate = args.GetIsolate();
    if (args.Length() < 3) {
        isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "Wrong number of arguments")));
        return;
    }

    if (!args[0]->IsInt32() || !args[1]->IsInt32()) {
        isolate->ThrowException(Exception::TypeError(
            String::NewFromUtf8(isolate, "Argument must be integer")));
        return;
    }

    MyCppClass* obj = ObjectWrap::Unwrap<MyCppClass>(args.Holder());

    int a = args[0]->Int32Value();
    int b = args[1]->Int32Value();
    v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[2]);

    obj->add(a, b, callback);
}

经验分享

  1. 理解V8引擎:Node.js基于Google的V8引擎,因此了解V8的一些基本概念(如v8::Localv8::Persistent等)是非常重要的。
  2. 使用Node.js API:熟悉Node.js的API(如node.h中的NODE_MODULE宏)可以帮助你更有效地创建和管理扩展。
  3. 封装C++对象:通常会将C++对象包装在JavaScript对象中,这样可以在JavaScript中访问C++的功能。
  4. 错误处理:在调用C++方法时,确保进行适当的错误处理,以避免未捕获的异常导致程序崩溃。

希望这些信息对你有所帮助!如果需要进一步的学习资料,可以查看Node.js的官方文档或搜索一些社区提供的教程。

回到顶部