简单上手nodejs调用c++(c++和js的混合编程)

因为项目的原因,最近经常使用node.js搭RESTful接口。
性能还是很不错啦,感觉比Spring Boot之类的要快。而且在不错的性能之外,只要程序结构组织好,别让太多的回调把程序结构搞乱,整体开发效率比Java快的就太多了。

如果想进一步提高效率,使用c++来优化部分模块是不错的选择。尤其可贵的是nodejs对于同c++的混合编程支持的很好,个人感觉跟写Python的扩展模块处于同样的易用水平。

我们从Hello World开始:
首先要有一个空白的工作目录,在其中建立一个node包管理文件package.json,内容为

 

{
  "name": "test-cpp-module",
  "version": "0.1.0",
  "private": true,
  "gypfile": true
}

随后在目录中执行命令:npm install node-addon-api --save安装nodejs扩展模块的开发支持包。这里假设你已经安装配置好了nodejs和相应的npm包管理工具,还有xcode的相关命令行编译工具。我们不重复这些基本工具的安装配置,需要的话请参考官网相关文档。
上面命令执行完成,我们就完成了基本开发环境的配置。

c++的模块由binding.gyp文件描述,并完成自动编译的相关配置工作,我们新建一个binding.gyp文件,内容为:

{
  "targets": [
    {
      "target_name": "democpp",
      "sources": [
        "democpp.cc"
      ],
      "include_dirs": [
        "
  • 文件中首先使用target_name指定了编译之后模块的名称。
  • sources指明c++的源文件,如果有多个文件,需要用逗号隔开,放到同一个数组中。
  • include_dirs是编译时使用的头文件引入路径,这里使用node -p执行node-addon-api模块中的预置变量。
  • dependencies是必须的,不要改变。
  • 后面部分,cflags!/cflags_cc!/defines三行指定如果c++程序碰到意外错误的时候,由NAPI接口来处理,而不是通常的由c++程序自己处理。这防止因为c++部分程序碰到意外直接就退出了程序,而是由nodejs程序来捕获处理。如果是在Linux中编译使用,有这三行就够了。
  • 但如果是在macOS上编译使用,则还要需要最后一项xcode-settings设置,意思相同,就是关闭macOS编译器的意外处理功能。
    最后是c++的源码,democpp.cc文件:
#include 

using namespace Napi;

String Hello(const CallbackInfo& info) {
  return String::New(info.Env(), "world");
}
Napi::Object  Init(Env env, Object exports) {
  exports.Set("hello", Function::New(env, Hello));
  return exports;
}
NODE_API_MODULE(addon, Init)

 

程序中引入napi.h头文件,使用Napi的namespace还有最后的NODE_API_MODULE(addon,Init)都是模板化的,照抄过来不用动。
Init函数中,使用exports.Set()引出要暴露给nodejs调用的函数。如果有多个需要引出的函数,就写多行。
Hello函数是我们主要完成工作的部分,本例中很简单,只是用字符串的方式返回一个“world”。

以上democpp.cc/binding.gyp/package.json三个文件准备好之后,在命令行执行:npm install,顺利的话会得到这样的输出信息:

 

$ npm install

> [email protected] install /home/andrew/Documents/dev/html/nodejs/callcpp
> node-gyp rebuild

  SOLINK_MODULE(target) Release/nothing.node
  CXX(target) Release/obj.target/democpp/democpp.o
  SOLINK_MODULE(target) Release/democpp.node

 这表示编译顺利完成了,如果碰到错误,可以根据错误信息去判断解决方案。通常都是环境配置缺少相关程序或者上述的三个文件有打字错误。
下面我们验证一下模块的编译结果,在命令行使用nodejs,引入编译的模块文件,然后调用hello函数来看看:

> $ node
> democpp=require("./build/Release/democpp.node")
{ hello: [Function] }
> democpp.hello()
'world'
> 

 

你可能感兴趣的:(Node.js)