以下Addons示例目的是为了帮助开发者开始开发Addons应用。这些示例调用V8 API,查阅V8在线帮助文档了解V8多种回调,并且V8 Embedder 教程来了解 handles,scopes,function templates等等


Node的C/C++扩展示例分类

函数参数

Addons将展示Node.js下能被JavaScript调用的具有代表性的导出示例和函数。当JS函数调用,输入的参数和返回值必须对应C/C++代码。以下举例说明如何读取JS的参数并返回值

//
// Created by http://www.flyfishonline.com on 16-6-16.
//

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

namespace J2Function{
    using v8::Exception;
    using v8::FunctionCallbackInfo;
    using v8::Isolate;
    using v8::Local;
    using v8::Number;
    using v8::Object;
    using v8::String;
    using v8::Value;

    //定义一个函数,实现一个加法
    //输入的参数是通过调用FunctionCallbackInfo<Value>& args获取的
    void Add(const FunctionCallbackInfo<Value>& args){
        Isolate* isolate = args.GetIsolate();

        if(args.Length()>2){
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate,"Wrong number of args")));
            return;
        }

        //因为Javascript是弱类型的,对JS传过来的值需要进行类型判断
        if(!args[0]->IsNumber() || !args[1]->IsNumber())
        {
            isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate,"Wrong arguments")));
            return;
        }

        //执行加法操作
        double value = args[0]->NumberValue()+
                       args[1]->NumberValue();

        //定义一个V8 Number
        Local<Number> num = Number::New(isolate,value);

        //通过FunctionCallbackInfo<Value>&类型参数设置返回值
        args.GetReturnValue().Set(num);
    }

    //初始化函数,绑定函数方法名 如绑定方法名为 'cadd'
    void Init(Local<Object> exports){
        NODE_SET_METHOD(exports,"cadd",Add);
    }

    //绑定到V8,NODE_MODULE是一个宏定义,
    // 添加过程是一系列的执行过程
    //NODE_MODULE(modname, regfunc)
    NODE_MODULE(j2c_add,Init);
}

一旦编译通过,这个Addon示例将能被Node.js下的require加载并调用。

var cadd = require('./build/Release/j2c_add.node');
console.log(cadd.cadd(5.0,11.3));

回调函数

这是对Addons用JavaScript函数调用C/C++函数,并执行。以面的例子民法了如何调用回调函数:

//
// Created by http://www.flyfishonline.com on 16-6-16.
// addon.cpp
#include <node/node.h>
#include <node/v8.h>
namespace demo {

    using v8::Function;
    using v8::FunctionCallbackInfo;
    using v8::Isolate;
    using v8::Local;
    using v8::Null;
    using v8::Object;
    using v8::String;
    using v8::Value;

    void RunCallback(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        //获取JS中的回调函数,并强制转换
        Local<Function> cb = Local<Function>::Cast(args[0]);
        const unsigned argc = 1;
        //创建一个返回值,名称任意
        Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
        //调用传过来的回调函数,返回值
        cb->Call(Null(isolate), argc, argv);
    }

    void Init(Local<Object> exports, Local<Object> module) {
        NODE_SET_METHOD(module, "exports", RunCallback);
    }

    NODE_MODULE(addon, Init)
}  // namespace demo

注意,这个示例使用了Init函数使用两个参数,void Init(Local<Object> , Local<Object>)函数第二个参数获取了module对象。这个对象允许重写exports的一个函数替代添加的函数作用exports的一个属性。

 Note that this example uses a two-argument form of Init() that receives the full module object as the second argument. This allows the Addon to completely overwrite exports with a single function instead of adding the function as a property of exports.

这段最后一句翻译的不通顺,若有同学有好一点的翻译,请留言吧!!

{
    "targets":[
        {
          "target_name":"addon_callback",
          "sources":["addon.cpp"]
        }
    ]
}
var add_callback = require("./build/Release/addon_callback.node");

add_callback(function (msg) {
    console.log(msg);
})

注意,这个示例的回调函数是异步调用。

#### 待续 Node-Addon-续4