Function
Definir uma function JavaScript é muito simples em NAPI-RS. Apenas uma simples Rust fn:
#[napi]
pub fn sum(a: u32, b: u32) -> u32 {
a + b
}
A coisa mais importante que você deve ter em mente é que as fn em NAPI-RS não suportam todos os tipos de Rust. Cada tipo de argumento deve implementar FromNapiValue, e cada tipo de retorno deve implementar ToNapiValue.
A matriz de conversão canônica — tipos de argumento e de retorno, direção, propriedade e features Cargo necessárias — está em Conversões de tipos. A versão resumida para funções:
- Números (
u32,i32,i64,f64),booleStringmapeiam para seus equivalentes JavaScript em ambas as direções. Option<T>como argumento aceitaT,nullouundefined(T | null | undefined); como tipo de retorno,Nonese tornanull(T | null).Vec<T>, tuplas,HashMape structs#[napi(object)]mapeiam para arrays JavaScript e objetos simples.Buffere os wrappers de typed-array mapeiam paraBuffereTypedArray.Function<Args, Return>eThreadsafeFunctionaceitam callbacks JavaScript com assinaturas totalmente tipadas (veja abaixo).- Uma
async fnou um retornoAsyncTaskmapeia paraPromise<T>.
Tipo de Retorno
O tipo de retorno de uma #[napi] fn é convertido com ToNapiValue e aparece diretamente no .d.ts gerado. Um retorno Result<T> lança uma exceção em caso de Err, em vez de produzir um valor. Veja a referência de Conversões de tipos para o mapeamento completo, incluindo os tipos de saída BigInt (i64n, i128, u128) e retornos assíncronos.
Function como parâmetro
Você pode passar uma Function como parâmetro para uma 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
Você também pode criar uma Function no lado do Rust, veja Env::create_function
FnArgs
Quando o número de parâmetros é maior que 1, você pode usar FnArgs para definir os parâmetros.
INFO
O tipo tuple pode ser convertido em FnArgs chamando .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
Assim como em JavaScript, você também pode usar apply para chamar uma Function com o valor this.
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
Veja Function Reference para mais detalhes.
build_threadsafe_function
Você pode construir uma ThreadsafeFunction a partir de uma Function chamando build_threadsafe_function.
O tipo de retorno de build_threadsafe_function é um ThreadsafeFunctionBuilder.
Por padrão, o ThreadsafeFunctionBuilder criará uma ThreadsafeFunction com as opções padrão:
INFO
Veja ThreadsafeFunction para os detalhes das opções
TIP
Como você pode passar ThreadsafeFunction e Arc<ThreadsafeFunction> diretamente para a #[napi] fn, use build_threadsafe_function apenas quando precisar criar uma ThreadsafeFunction dinamicamente.
max_queue_sizeé0weakéfalsecallee_handledétrueerror_statusénapi::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(())
}