第一個 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
程式。