Skip to content

Function

Definir uma function JavaScript é muito simples em NAPI-RS. Apenas uma simples Rust fn:

lib.rs
rust
#[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), bool e String mapeiam para seus equivalentes JavaScript em ambas as direções.
  • Option<T> como argumento aceita T, null ou undefined (T | null | undefined); como tipo de retorno, None se torna null (T | null).
  • Vec<T>, tuplas, HashMap e structs #[napi(object)] mapeiam para arrays JavaScript e objetos simples.
  • Buffer e os wrappers de typed-array mapeiam para Buffer e TypedArray.
  • Function<Args, Return> e ThreadsafeFunction aceitam callbacks JavaScript com assinaturas totalmente tipadas (veja abaixo).
  • Uma async fn ou um retorno AsyncTask mapeia para Promise<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:

lib.rs
rust
use napi::bindgen_prelude::*;
use napi_derive::napi;

#[napi]
pub fn call_function(callback: Function<u32, u32>) -> Result<u32> {
  callback.call(1)
}

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

index.d.ts
ts
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().

lib.rs
rust
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()) 
}

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

index.d.ts
ts
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.

lib.rs
rust
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, ())
}
index.ts
ts
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 é 0
  • weak é false
  • callee_handled é true
  • error_status é napi::Status
lib.rs
rust
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(())
}
Última atualização em
LongYinan