通过 SWIG 构建 Node.js Native c++工程

介绍

有人说javascript是最优美的语言,确实也是。然而,了解过javascript发展史的人都知道,在早年的浏览器大战中能够脱颖而出,也绝非易事。更何况,javascript的标准化过程也是曲折艰难。然而,自从Ryan Dahl在2009年js峰会上介绍了Node.js以后,让程序员们大开眼界。Node.js融合了google的v8 javascript引擎,引入了服务器端常用的事件处理机制,使得javascript语言也可以用来实现服务端程序,前端程序员写一个服务器不再是一件空难的事情。当然,业界有很多项目也尝试用Node.js来实现服务器逻辑。

然而,javascript毕竟是脚本语言,在一些计算密集型,实时性要求高的产品中,采用Native(主要是通过c++)实现这些逻辑显得尤为重要。

Node.js本身常用的一种叫Nan(Native Abstract for Node.js)的方式,非常不错。其github的项目地址:https://github.com/nodejs/nan

而,本文要介绍的是通过SWIG来实现javascript和c++的融合。

SWIG

介绍

SWIG的官网地址是:http://www.swig.org

SWIG主要是一个接口编译器,将C/C++程序暴露的API描述在一个后缀是(.i)的文件里面,然后通过swig编译器生成c++源代码的一个wrapper,

生成的代码可以在脚本语言的解释器平台上执行,从而实现了脚本语言调用c/c++程序API的目的。

SWIG只是代码生成工具,不需要依赖任何平台和库。

SWIG支持的脚本语言有很多:比如tcl,java,php5,php7,python等很多,当然也包含javascript了。

SWIG项目的意义,以及很多优势在官网里面有详细的介绍,里面也有很多参考资源,可以方便进一步的学习。

本文我们只是通过一个简单的demo来说明,swig的基本用法。

安装

目前支持SWIG的系统有windows,mac,cygwin,linux,等很多unix-like系统。

作者本人用的是cygwin环境。

具体安装过程步骤相对简单,参考官网说明即可。

安装完成后,打开命令行做如下的测试:

   $ swig -version

    SWIG Version 3.0.12

    Compiled with g++ [x86_64-unknown-cygwin]

    Configured options: +pcre

    $ swig --help
     Target Language Options
     -allegrocl      - Generate ALLEGROCL wrappers

SWIG对C/C++的支持

因为SWIG主要目的是实现不同语言的互通,所以并没有完全支持c++语言的所有特性。比如,c++的多重继承,运算符重载,成员函数重载等。

当然,基本常用的语法都是支持,比如虚函数,多态,还有c++11新标准也支持。

接口文件说明

swig的接口文件如下,文件后缀名是(.i).

  1 %module example
  2 %{
  3 #include "c_example.h"
  4 #include "shape.h"
  5 %}
  6
  7 extern void print_c();
  8 extern const char *get_c_desc();
  9
 10 %include "shape.h"
  

%module : 是模块说明指令,这个是必须的,我们在node.js中通过require引入需要的。

%{ %} : 中包含的内容,swig是不做任何处理的,直接导入到最终生成的文件中。这个类似yacc/bison的的%{ %}指令。所以,我们是可以在这个指令块内,写一些C/C++代码的。例子中 c_example.h是一个c语言API的声明。shape.h是一个c++头文件的声明,包含了继承,多态,静态成员变量等特性。

第7-8行:是暴露给脚本语言访问的的接口。这里其实就是一个wrapper。

第10 行:用了%include 指令,这是将shape.h中的所有接口都暴露给脚本语言。如果说你原始头文件的所有接口都暴露,可以直接这样包含。如果,原始头文件中包含的内容太多不想暴露,或者是包含了swig不支持的语法,需要像7-8行那样,做一个wrapper。

具体操作

swig代码生成

写完接口文件,我们就可以用swig生成代码。如下,

swig.exe -c++ -javascript -node example.i

执行完上面的命令会在当前目录下面生成一个example_wrap.cxx的文件。

-c++ : 只是表示native代码是c++代码,这里需要说明的是C/C++语言都需要增加此选项。

-javascript: 表示生成的脚本语言是javascript语言。

-node:是执行javascript的引擎。

最后是接口文件名称。

特别说明:这里的c/c++语言后缀必须是c++语言的文件后缀,比如(*.cxx, *.cpp)等,否则编译的时候会出错。

构建Native编译工程

这里怎么构建Node.js工程,以及package.json的说明就不再讲了。

构建Node.js native 编译, 创建一个swig-js工程目录,结构如下:

swig-js
│  binding.gyp //Native build 文件
│  index.js //js测试文件
│  package-lock.json
│  package.json
└─src
     | c_example.cxx
     | c_example.h
     | example.i // 接口文件
     | example_wrap.cxx // swig生成的文件
     | shape.cxx
     | shape.h

首先, 创建binding.gyp文件 , 内容如下:

{
  "targets": [
    {
      "target_name": "example",
      "include_dirs":
      [
          'src'
      ],
      "sources":
       [
            "src/c_example.cxx",
            "src/shape.cxx",
            "src/example_wrap.cxx"
       ]
    }
  ]
}
其次,编译, 经过下面过程的编译,就生成了native代码。
   npm install node-gyp -g //安装native build工具

   node-gyp configure

   node-gyp build

最后,测试,index.js测试代码如下:


var example = require('./build/Release/example');

example.print_c();

console.log(example.get_c_desc());

var shape = new example.Circle(2);

shape.move(2, 3);

let square = new example.Square(5);

console.log('The square area='+square.area());

执行:

$ node index.js
I'm c swig test.
Test c module
Move from(0, 0) to (2, 3)
The square area=25
经过上面的步骤,通过swig 进行javascript和c++的融合开发就完成了。

特别说明

从node7.0开始,删除了一些api,比如, v8::Object::GetHiddenValue 。因为swig的开发目前还有支持最新的的node版本,所以需要node 7.0以下的版本来测试。

笔者用的是v6.17.1 node版本。

样例代码路径:https://github.com/avdance/AVDemo/tree/master/code/swig-js

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,095评论 0 3
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,421评论 1 45
  • 系列文章导航 模块(一) CommonJs,AMD, CMD, UMD 本文参考阮一峰 ES6入门 Module的...
    合肥黑阅读 6,095评论 0 4
  • TITLE: 编程语言乱炖 码农最大的烦恼——编程语言太多。不是我不学习,这世界变化快! 有时候还是蛮怀念十几、二...
    码园老农阅读 5,295评论 2 35
  • 何妍最后爱上傅慎行了吗? 我能肯定的给出答案— 不,从来没有。 傅慎行,或者叫做沈知节,是个彻头彻尾的变态 同意让...
    春天的姜卷卷花阅读 9,408评论 0 1