SWIG与nodejs入门

前言

Javascipt是一种基于原型的脚本语言。它是动态的,弱类型的语言。它可以说是最流行的Web开发语言。Javascript已经超越了基于浏览器的脚本语言,并且与node.js一起,它也被用作后端开发语言。

SWIG Javascript目前支持JavascriptCore,Safari / Webkit使用的Javascript引擎,以及Chromium和node.js使用的v8。

运行 SWIG

假设您像下面这样,定义了一个SWIG模块:

%module example
%{
#include "example.h"
%}
int gcd(int x, int y);
extern double Foo;

要构建Javascript模块,请使用 -javascript 选项和所希望的目标引擎如:-jsc-v8-node 运行SWIG。node生成器基本上委托给v8生成器并添加一些必要的预处理器定义。

$ swig -javascript -jsc example.i

如果构建C ++扩展,请添加-c ++选项:

$ swig -c++ -javascript -jsc example.i

SWIG生成的V8代码应适用于从3.11.10到3.29.14及更高版本的大多数版本。 大于等于 4.3.0的 V8 API头定义了SWIG用于决定其正在编译的V8版本的常量。小于 4.3的版本,在运行 SWIG时,你要指定V8的版本。版本号是一个16进制的常量,但是常量被读作十进制数字对。如 V8 3.25.30使用常量 0x032530。这种模式不能表达超过 99的数字,但此常量仅在V8版本小于 4.3.0时才使用。并且目前没有任何 V8版本超过了 99。例如:

$ swig -c++ -javascript -v8 -DV8_VERSION=0x032530 example.i

如果你的目标 V8 版本直超过 4.3.0,你应该像下面这样运行 swig:

$ swig -c++ -javascript -v8 example.i

它将创建一个 名为 example_wrap.c 或 example_wrap.cxx 的 C/C++ 文件。产生的 C 源文件包括许多需要被编译底层wapper并与剩下的C/C++应用链接到一起生成一个扩展模块。

wraper文件的名子来自于输入文件。例如, 如果输入文件是 example.i,那么wraper文件的名子就是example_wrap.c。如果要改变它,你可以使用 -o 选项。wrapper模块将导出一个必须被调用的函数,以便将它注册到 javascript解释器中。例如,如果你的模块命名为 example,那么对于 JavascriptCore 对应的初始化函数应该如下:

bool example_initialize(JSGlobalContextRef context, JSObjectRef *exports)

对于 V8

void example_initialize(v8::Handle<v8::Object> exports)

注意: V8使用C ++ API,因此,生成的模块必须编译为C ++

运行测试和例子

对于测试和例子的配置当前仅支持 Linux和Mac,而不支持 MinGW(Windows)。

默认解释器是node.js,因为它在所有平台上都可用并且使用方便。

使用JavascriptCore运行示例需要安装libjavascriptcoregtk-1.0,例如,在Ubuntu下安装

$ sudo apt-get install libjavascriptcoregtk-1.0-dev

使用V8运行需要libv8:

$ sudo apt-get install libv8-dev

可以使用示例运行

$ make check-javascript-examples ENGINE=jsc

ENGINE可以是node,jsc或v8。

测试套件可以使用

$ make check-javascript-test-suite ENGINE=jsc

您可以指定用于运行示例和测试的特定V8版本

$ make check-javascript-examples V8_VERSION=0x032530 ENGINE=v8

创建 node.js 扩展

对于Mac和Windows用户可以下载安装包安装node.js。对于Linux用户,你即可以通过 build 源码安装它,也可以通过包安装。

由于v8是用C ++编写的,并且作为C ++库,因此使用与构建v8相同的编译器标志来编译模块至关重要。为了简化操作,node.js提供了一个名为node-gyp的构建工具。

你必须使用npm安装它:

sudo npm install -g node-gyp

node-gyp需要一个名为binding.gyp的配置文件,该文件基本上是JSON格式,并且符合与Google的构建工具gyp一样的格式

binding.gyp:

{
  "targets": [
    {
      "target_name": "example",
      "sources": [ "example.cxx", "example_wrap.cxx" ]
    }
  ]
}

首先使用SWIG创建包装器:

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

然后运行node-gyp build来实际创建模块:

$ node-gyp build

这将创建一个包含Native模块的build文件夹。要使用扩展程序,您需要在Javascript源文件中“require”它:

require("./build/Release/example")

例子部分中给出了更详细的解释。

问题

  • 'module' 对免没有'script_main'属性 当gyp作为分发包安装时会发生此错误。它似乎已经过时了。删除它可以解决问题。
sudo apt-get remove gyp

例子

这里展示一些基本例子和更多的细节:

/* File : example.i */
%module example

%inline %{
extern int    gcd(int x, int y);
extern double Foo;
%}

要使其node扩展,必须创建binding.gyp:

{
  "targets": [
    {
      "target_name": "example",
      "sources": [ "example.cxx", "example_wrap.cxx" ]
    }
  ]
}

然后node-gyp用于构建扩展:

$ node-gyp configure build

从'nodejs`应用程序将像这样使用扩展:

// import the extension via require
var example = require("./build/Release/example");

// calling the global method
var x = 42;
var y = 105;
var g = example.gcd(x, y);

// Accessing the global variable
var f = example.Foo;
example.Foo = 3.1415926;

首先,加载先前build的扩展example 模块。模块中的全局方法和变量是有效的。

常见的示例类定义了三个类:Shape,Circle和Square:

class Shape {
public:
  Shape() {
    nshapes++;
  }
  virtual ~Shape() {
    nshapes--;
  }
  double  x, y;
  void    move(double dx, double dy);
  virtual double area(void) = 0;
  virtual double perimeter(void) = 0;
  static  int nshapes;
};

class Circle : public Shape {
private:
  double radius;
public:
  Circle(double r) : radius(r) { }
  virtual double area(void);
  virtual double perimeter(void);
};

class Square : public Shape {
private:
  double width;
public:
  Square(double w) : width(w) { }
  virtual double area(void);
  virtual double perimeter(void);
};

Circle和Square继承自Shape。Shape具有静态变量nshapes, move函数不能被重载(非虚函数),并且有两个抽象函数areaperimeter(纯虚函数)必须由子类重载。

nodejs扩展的build方式与simple示例相同。

在Javascript中,它可以使用如下:

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

// local aliases for convenience
var Shape = example.Shape;
var Circle = example.Circle;
var Square = example.Square;

// creating new instances using the 'new' operator
var c = new Circle(10);
var s = new Square(10);

// accessing a static member
Shape.nshapes;

// accessing member variables
c.x = 20;
c.y = 30;
s.x = -10;
s.y = 5;

// calling some methods
c.area();
c.perimeter();
s.area();
s.perimeter();

// instantiation of Shape is not permitted
new Shape();

小结

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • TypeScript入门

    TypeScript 是最近比较新的一门语言,它主要用于代替 JavaScript。为什么要推出 TypeScript 来代替 JavaScript呢? 主要...

    音视频_李超
  • 音视频直播技术--Android视频采集(Camera2)

    今天为大家介绍一下如何在 Android 上进行视频采集。在 Android 系统下有两套 API 可以进行视频采集,它们是 Camera 和 Camera2 ...

    音视频_李超
  • 音视频直播技术--视频渲染之EGL

    我们在Andriod系统下做视频渲染时要使用 OpengGL ES, 而使用 OpengGL ES 就不得不提到 EGL。那么EGL是什么呢?它又在渲染时起到什...

    音视频_李超
  • Go实战--golang中使用RethinkDB(gorethink/gorethink.v3)

    生命不止,继续go go go !!! 关于golang中操作数据库,曾经介绍了不少: Go实战–go语言操作sqlite数据库(The way to go) ...

    程序员的酒和故事
  • Learn Linux Programming the Recursive Way

    HaHack
  • 学员故事丨告诉你如何变得优秀

    腾讯NEXT学位
  • 论买奶粉的正确姿势,文本数据挖掘有话要说

    面对市场上玲琅满目的奶粉,消费者时常不知如何选择。作为一个擅长用数据解决消费问题的网红,DT君一向推崇用户评论文本数据的挖掘。来自KPMG大数据挖掘团队的数据侠...

    DT数据侠
  • 我的世界中国版发布会于4月7日在水立方召开 将公布首测日期

    Youngxj
  • 【学员干货】App常见性能测试点

    (app除了这些性能测试,还有:手机版本号兼容性,屏幕分辨率兼容性,稳定性测试,安全测试等,后续会持续更新… 流量测试同这些一起更新,这里就不在说明了 )

    新梦想IT职业教育
  • 给学徒的GEO作业

    看懂文章:https://www.jci.org/articles/view/96060/figure/1 看其C子图里面的TRAF4基因在4个数据集的表达量,...

    生信技能树

扫码关注云+社区

领取腾讯云代金券