Function
Defining a JavaScript function is very simple in NAPI-RS. Just a plain Rust fn:
#[napi]
pub fn sum(a: u32, b: u32) -> u32 {
a + b
}
The most important thing you should keep in mind is NAPI-RS fn does not support every Rust type. Each argument type must implement FromNapiValue, and each return type must implement ToNapiValue.
The canonical conversion matrix — argument and return types, direction, ownership, and required Cargo features — lives in Type conversions. The short version for functions:
- Numbers (
u32,i32,i64,f64),bool, andStringmap to their JavaScript equivalents in both directions. Option<T>as an argument acceptsT,null, orundefined(T | null | undefined); as a return type,Nonebecomesnull(T | null).Vec<T>, tuples,HashMap, and#[napi(object)]structs map to JavaScript arrays and plain objects.Bufferand the typed-array wrappers map toBufferandTypedArray.Function<Args, Return>andThreadsafeFunctionaccept JavaScript callbacks with fully typed signatures (see below).- An
async fnor anAsyncTaskreturn maps toPromise<T>.
Return Type
The return type of a #[napi] fn is converted with ToNapiValue and appears directly in the generated .d.ts. A Result<T> return throws on Err instead of producing a value. See the Type conversions reference for the complete mapping, including BigInt output types (i64n, i128, u128) and async returns.
Function as parameter
You can pass a Function as a parameter to a fn:
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
pub fn call_function(callback: Function<u32, u32>) -> Result<u32> {
callback.call(1)
}
⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
export declare function callFunction(callback: (arg: number) => number): number
INFO
You can also create a Function at the Rust side, see Env::create_function
FnArgs
When the number of parameters exceeds 1, you can use FnArgs to define the parameters.
INFO
The tuple type can be converted to FnArgs by calling .into().
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
pub fn call_function_with_args(callback: Function<FnArgs<(u32, u32)>, u32>) -> Result<u32> {
callback.call((1, 2).into())
}
⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️
export declare function callFunctionWithArgs(
callback: (arg1: number, arg2: number) => number,
): number
apply
Like JavaScript, you can also use apply to call a Function with the this value.
use napi::bindgen_prelude::*;
use napi_derive::napi;
#[napi]
pub struct RustClass {
pub name: String,
}
#[napi]
impl RustClass {
#[napi(constructor)]
pub fn new(name: String) -> Self {
Self { name }
}
}
#[napi]
pub fn call_function_with_apply(
this: ClassInstance<RustClass>,
callback: Function<(), ()>,
) -> Result<()> {
callback.apply(this, ())
}
import { callFunctionWithApply, RustClass } from './index.js'
const rustClass = new RustClass('foo')
callFunctionWithApply(rustClass, function () {
console.log(this.name) // foo
})
create_ref
See Function Reference for more details.
build_threadsafe_function
You can build a ThreadsafeFunction from a Function by calling build_threadsafe_function.
The return type of the build_threadsafe_function is a ThreadsafeFunctionBuilder.
By default, the ThreadsafeFunctionBuilder will create a ThreadsafeFunction with the default options:
INFO
See ThreadsafeFunction for the details of options
TIP
Since you can pass ThreadsafeFunction and Arc<ThreadsafeFunction> directly to the #[napi] fn, only use the build_threadsafe_function when you are need to create a ThreadsafeFunction dynamically.
max_queue_sizeis0weakisfalsecallee_handledistrueerror_statusisnapi::Status
use napi::{bindgen_prelude::*, threadsafe_function::ThreadsafeFunctionCallMode};
use napi_derive::napi;
#[napi]
pub fn build_threadsafe_function_from_function(
callback: Function<FnArgs<(u32, u32)>, u32>,
) -> Result<()> {
let tsfn = callback.build_threadsafe_function().build()?;
let jh = std::thread::spawn(move || {
tsfn.call((1, 2).into(), ThreadsafeFunctionCallMode::NonBlocking);
});
Ok(())
}