第一個 neon 程式
neon nodejs rust -Why
強強聯手
How
如果沒有 rust,則先安裝 Rust。
一個 Neon 專案是一個 Node package,也是一個 Rust crate。
使用 npm init neon cpu-count 產生一個叫 cpu-count 的 Neon 專案目錄結構。
Rust 程式通常放在 src 目錄中。
設定檔 Cargo.toml 提供給 Neon 和 Rust 使用。
而 package.json 則是作為 nodejs 與整個程式的設定檔。
現在整的程式是空的,但卻是可以編譯的。
先利用 npm install 將需要的部分安裝起來。
package.json
{
"name": "cpu-count",
"version": "0.1.0",
"description": "",
"main": "index.node",
"scripts": {
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
"build-debug": "npm run build --",
"build-release": "npm run build -- --release",
"install": "npm run build-release",
"test": "cargo test"
},
"author": "",
"license": "ISC",
"devDependencies": {
"cargo-cp-artifact": "^0.1"
}
}
根據 package.json,npm 會安裝 cargo-cp-artifact 套件並執行編譯。
這時會多出 target 目錄,這是 Rust 用來構建的目錄。
使用 cargo clean 可以清除這些編譯檔。
在根目錄下會多出 index.node,這是編譯最後的產物。
在 Rust 程式中只是簡單提供一個 hello 函式的接口,該函式被呼叫時會輸出一個 hello node 字串。
src/lib.rs
use neon::prelude::*;
fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
Ok(cx.string("hello node"))
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("hello", hello)?;
Ok(())
}
現在讓我們在 nodejs 的 REPL 環境中執行編譯程式。
> require('.').hello()
// hello node
退出 nodejs 的 REPL 環境。
在 Cargo.toml 加入對 num_cpus 套件的依賴。
Cargo.toml
[dependencies]
num_cpus = "1"
增加一個函式 get_num_cpus,並將它導出。
src/lib.rs
// add get_num_cpus
fn get_num_cpus(mut cx: FunctionContext) -> JsResult<JsNumber> {
Ok(cx.number(num_cpus::get() as f64))
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
cx.export_function("hello", hello)?;
// export function
cx.export_function("get", get_num_cpus)?;
Ok(())
}
然後借用
npm run build -- --release
重新編譯。
進入 nodejs 的 REPL 環境。
> const cpuCount = require('.')
> cpuCount.get()
// cpu num
這就是我們第一個 neon 。
功能是使用 nodejs 呼叫 rust 程式,取得 cpu 數量後回傳給 nodejs 程式。