注入 Env
#[napi]
宏是对 Node-API
的一个非常高级的抽象,大多数情况下,你使用 Rust 的原生 API 和包。
但是有时候你仍然需要访问底层的 Node-API
,
例如调用 napi_async_cleanup_hook
(opens in a new tab)
或 napi_adjust_external_memory
(opens in a new tab)。
对于这种情况,NAPI-RS 允许你通过 #[napi]
装饰,将 Env
注入到你的 fn
中。
use napi::{Env, bindgen_prelude::*};
#[napi]
fn call_env(env: Env, length: u32) -> Result<External<Vec<u32>>> {
env.adjust_external_memory(length as i64)?;
Ok(External::new(vec![0; length as usize]))
}
Env
将会被 NAPI-RS 自动注入,这不会影响 JavaScript 端的参数类型:
export function callEnv(length: number) -> ExternalObject<number[]>
您还可以在 impl
块中注入 Env
:
use napi::bindgen_prelude::*;
// A complex struct which can not be exposed into JavaScript directly.
struct QueryEngine {}
#[napi(js_name = "QueryEngine")]
struct JsQueryEngine {
engine: QueryEngine,
}
#[napi]
impl JsQueryEngine {
#[napi(factory)]
pub fn with_initial_count(count: u32) -> Self {
JsQueryEngine { engine: QueryEngine::with_initial_count(count) }
}
/// Class method
#[napi]
pub fn query(&self, env: Env, query: String) -> napi::Result<String> {
self.engine.query(query).map_err(|err| Error::new(Status::GenericFailure, format!("Query failed {}", err)))
}
}
这个行为和纯 fn
是一样的。