Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7278685
  • 博文数量: 512
  • 博客积分: 12019
  • 博客等级: 上将
  • 技术积分: 6857
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-01 16:46
文章分类

全部博文(512)

文章存档

2024年(2)

2022年(2)

2021年(6)

2020年(59)

2019年(4)

2018年(10)

2017年(5)

2016年(2)

2015年(4)

2014年(4)

2013年(16)

2012年(47)

2011年(65)

2010年(46)

2009年(34)

2008年(52)

2007年(52)

2006年(80)

2005年(22)

分类: JavaScript

2014-06-24 10:41:09

转载于

从node-waf到node-gyp
node进入0.8版本之后,开始替换之前编译C++模块的编译工具,从node-waf向node-gyp转换,暂时是两者都支持,之后会不在支持node-waf编译。因此要写node的C++扩展,首先需要了解如何编写node-gyp的配置文件。
node-gyp的配置文件名字为binding.gyp,它是一个纯JSON对象,相对于node-waf的配置文件来说,写惯了javascript的同学会更加熟悉。
Hello node-gyp
先来看一个最简单的使用示例。
C模块部分提供了一个hello方法,返回一个字符串world:

点击(此处)折叠或打开

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


  3. using namespace v8;


  4. Handle<Value> Method(const Arguments& args) {
  5.   HandleScope scope;
  6.   return scope.Close(String::New("world"));
  7. }


  8. void init(Handle<Object> target) {
  9.   NODE_SET_METHOD(target, "hello", Method);
  10. }


  11. NODE_MODULE(binding, init);
  12. binding.gyp指定C部分源文件路径和最终生成模块的名称,此例中将会生成一个可以被node调用的binding.node文件。
  13. {
  14.   'targets': [
  15.     {
  16.       'target_name': 'binding',
  17.       'sources': [ 'binding.cc' ]
  18.     }
  19.   ]
  20. }


js调用代码:

点击(此处)折叠或打开

  1. var assert = require('assert');
  2. var binding = require('./build/Release/binding');
  3. assert.equal('world', binding.hello());
  4. console.log('binding.hello() =', binding.hello());


一个复杂一点的例子
在编写node-hsf的时候,由于涉及到第三方库的引入,以及对mac和linux的兼容,因此编译脚本会相对更加复杂。

点击(此处)折叠或打开

  1. {
  2.   'targets': [
  3.     {
  4.       'target_name': 'hsfProtocol',
  5.       'sources': ['hsf_protocol.cc'],
  6.       'cflags': ['-fexceptions', '-Wall', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE_SOURCE', '-O2'], //编译选项
  7.       'cflags_cc': ['-fexceptions', '-Wall', '-D_FILE_OFFSET_BITS=64','-D_LARGEFILE_SOURCE', '-O2'],
  8.       'cflags!': ['-fno-exceptions'], //关闭的编译选项
  9.       'cflags!_cc': ['-fno-exceptions'],
  10.       'conditions': [
  11.         ['OS=="mac"', { //满足此条件后开启
  12.           'xcode_settings': {
  13.             'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
  14.           }
  15.         }]
  16.         ],
  17.       'include_dirs': [ //引用第三方库的头文件路径
  18.                        '../hsf_protocol/utils',
  19.                        '../hsf_protocol/objects',
  20.                        '../hsf_protocol/hessian',
  21.                        '../hsf_protocol/hsf']
  22.     }
  23.   ]
  24. }


注意事项:
1. 如果遇到了exception handling disabled, use -fexceptions to enable错误,需要添加编译选项-fexceptions。如果还是不行,则可能是因为该版本的node-gyp默认启用了-fno-exceptions选项,因此通过cflags!和cflags!_cc中指定关闭掉这个默认开启的选项。
2. conditions内可以根据一些条件来添加选项,例如根据操作系统来添加一些编译条件。
3. 依赖的第三方动态链接库可能无法引入,出现这种情况可以把静态库和node-gyp生成的中间文件一起编译成最终的模块。

点击(此处)折叠或打开

  1. #!/bin/bash


  2. HSFPROTOCOL_HOME="`pwd`/hsf_protocol"
  3. SYSTEM=`uname -s`
  4. EXTRA_FLAG="";


  5. if [ $SYSTEM = "Darwin" ] ; then #判断是否是mac操作系统
  6.   # for mac
  7.   EXTRA_FLAG="-flat_namespace -undefined suppress"
  8.   echo 'building for mac'
  9. fi


node-gyp configure build
gcc -fcc1-exceptions -fexceptions -O2 -o hsfProtocol.node ./build/Release/obj.target/hsfProtocol/hsf_protocol.o \
  $HSFPROTOCOL_HOME/libhsf.a -shared -fPic $EXTRA_FLAG
可以看到在上面脚本中,把node-gyp生成的中间文件hsf_protocol.o与静态库libhsf.a编译成最终的hsfProtocol.node。为了进行跨平台的编译,如果是mac操作系统,则需要多添加-flat_namespace -undefined suppress这几个编译选项。
关于node-gyp的一些其他参考资料和范例和更复杂的用法,请查阅node-gyp in github。

阅读(5468) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~