快速开发NodeJS原生扩展--napi-rs

289 阅读2分钟

项目有个需求,要求实现Chrome的任务管理器模块。

image.png

进程管理相关的API跟操作系统强相关,所以这里使用node的原生扩展比较贴合实际。但是官方的NAPI需要配置node-gyp、写binding,还要到处查文档编写平台相关的编译参数。想想就头大...

好在系统调用为了方便扩展,都会有一版C兼容的API。这个时候rust的ffi模块就派上用场了。

前期准备

  • rust -- windows请使用官网的exe安装,chocolate安装的rustup是gnu兼容的包,不利于对接win32 api
  • napi-rs napi.rs/cn/docs/int…

起步阶段

通过上述步骤,一个脚手架工程就被快速创建好了。yarn build然后yarn test就可以快速验证代码了。

调试Rust代码 【VS Code】

每天上班写bug,怎么能不准备一手debug工具呢?JS调试的教程到处都有,这里单独说一下rust代码的调试配置。

  • MacOS: CodeLLDB Extension ID: vadimcn.vscode-lldb
  • Windows: C/C++ Extension ID: ms-vscode.cpptools

扩展安装好之后,就可以配置VS Code了,

  1. 允许debug,添加"debug.allowBreakpointsEverywhere": true到工程目录的.vscode/settings.json。或者在图形化设置中搜索everywhere image.png
  2. 编辑.vscode/launch.json文件,生成调试配置。因为不同平台使用的API、依赖库迥异,所以这里拆成两个不同的入口文件target/debug/testtarget/debug/test-win.exe来进行各自的调试。
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(Windows) Launch",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceRoot}/target/debug/test_win.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceRoot}",
            "preLaunchTask": "cargo build:test-win",
            "environment": [],
            "console": "internalConsole"
        },
        {
            "name": "(OSX) Launch",
            "type": "lldb",
            "request": "launch",
            "cargo": { // lldb扩展对rust有特殊的支持,这样就不必依赖外部的task来编译调试产物了
                "args": ["build", "--bin=test"],  // Cargo command line to build the debug target
            },
            "cwd": "${workspaceRoot}",
            "console": "internalConsole"
        }
    ]
}
  1. .vscode/tasks.json每次调试前构建调试产物,task中的label必须跟configurations中的preLaunchTask完全一致
{
    "version": "2.0.0",
    "tasks": [
      {
        "label": "cargo build:test-win",
        "type": "shell",
        "command": "cargo",
        "args": [
          "build",
          "--bin",
          "test_win"
        ],
        "group": {
          "kind": "build",
          "isDefault": true
        }
      }
    ]
  }

配置完成后,在debug视图就可以选中对应的configuration进行调试了。

image.png

或者在编辑器窗口内,通过快速debug入口开始调试。

image.png

最终效果:

image.png

会用工具的程序员才是一个合格进化的好猩猩。

踩坑1:

如果mac下,DEBUG CONSOLE中一直提示错误码为-1的时候,可能是插件内置的lldb不兼容,需要重新配置CodeLLDB中lldb的选择。类似下面的输出:

Console is in 'commands' mode, prefix expressions with '?'.
Launching: /Users/xxx/rust-workspace/process-util/target/debug/test
Launched process 15288
Process exited with code -1.

具体步骤为CMD + SHIFT + P,选择LLDB: Use Alternated Backend...,然后输入lldb,会提示在.vscode/settings.json中添加lldb.library字段。示例如下:

{
  "lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB"
}

踩坑2:

napi-rs会要求输入package name,npm对这里的要求比较宽松。但是rust中crate的名称不能有-(中划线 aka. dash)。所以package name最好不要使用-。可以使用napi rename来挽救一下,或者手动修改Cargo.toml等文件中的定义。