Windows上编译NodeJS native extension
发布于 13 年前 作者 bombworm 13075 次浏览 最后一次编辑是 8 年前

必备工具:VC 2010 (嫌太大Express版即可),Python

NodeJS完成windows上加载扩展功能很久了,一直懒得去试。过年闲得无聊尝试了一把,顺便试了下gyp编译,确实比node-waf好用得多。

首先从node_source\test\addons\hello-world下把3个文件copy出来,放入新的目录,同时把编译出来的node.lib也放入那个目录

然后修改binding.gyp如下,红色部分为新增内容

{

  'targets': [

    {

      'target_name': 'binding',

      'sources': [ 'binding.cc' ],

      'libraries': ['-lnode.lib']

    }

  ]

}

另外还要改一下binding.cc,同样红色部分为新增内容:

extern "C" {

  NODE_MODULE_EXPORT void init(Handle<Object> target);

}

下一步可以使用gyp生成VC项目文件:

python node_source\tools\gyp_addon binding.gyp

接下来要设置一下VC的环境变量,命令行下找到如下路径:Microsoft Visual Studio 10.0\VC\vcvarsall.bat

执行完后会有提示:

Setting environment for using Microsoft Visual Studio 2010 x86 tools.

这样就可以继续下一步操作了,命令行输入:

msbuild binding.sln

一切顺利的话可以在Debug目录下找到我们想要的binding.node,那么测试一下吧,同样的,改一下

test.js:

var binding = require('./out/Release/binding');

改为

var binding = require('./Debug/binding');

在命令行输入node test.js,顺利得到输出:

binding.hello() = world

到这里模块编译就完成了。

然后我开始解释增加NODE_MODULE_EXPORT的原因。

首先加载模块涉及的是Module.js里加载.node扩展时调用的代码:

Module._extensions['.node'] = function(module, filename) {

  process.dlopen(filename, module.exports);

};

实际调用了Node.cc中的 Handle<Value> DLOpen(const v8::Arguments& args)

成功加载扩展后会查找导出的init函数绑定到mod->register_func

uv_dlsym(lib, "init", reinterpret_cast<void**>(&mod->register_func));

确定模块版本和node版本一致后调用 mod->register_func(target); // init

如果没有导出init函数,node会报如下错误: Error: unknown error

    at Object..node (module.js:463:11)

至于检查是否导出了init函数,可以用VC提供的dumpbin工具:dumpbin /EXPORTS binding.node|find "init"

如果没有内容输出,就代表没有导出,成功导出的话就可以看到类似输出:

123 7A 00001334 init = @ILT+815(_init)

'libraries': ['-lnode.lib']那一句是为了在连接时加上node.lib,不然会报很多unresolved external symbol的错误,这里可以把路径直接写为node编译出来的路径,这样就省去了反复copy新的node.lib的麻烦

markdown貌似没找到更改颜色的…我在原文中都标了不同的颜色突出重点 原文连接:http://hi.baidu.com/%E8%99%AB%E7%9A%84%E4%BC%A0%E4%BA%BA/blog/item/fa34afdcf9ab53bfcd1166b7.html

回到顶部