napi_sys/
lib.rs

1// borrowed from https://github.com/neon-bindings/neon/tree/main/crates/neon/src/sys/bindings
2
3#![allow(ambiguous_glob_reexports)]
4
5#[cfg(any(
6  target_env = "msvc",
7  all(not(target_family = "wasm"), feature = "dyn-symbols")
8))]
9macro_rules! generate {
10  (@stub_fn $name:ident($($param:ident: $ptype:ty,)*) -> napi_status) => {
11    unsafe extern "C" fn $name($(_: $ptype,)*) -> napi_status {
12      eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
13      1
14    }
15  };
16  (@stub_fn $name:ident($($param:ident: $ptype:ty,)*) -> $rtype:ty) => {
17    unsafe extern "C" fn $name($(_: $ptype,)*) -> $rtype {
18      eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
19      unsafe { std::mem::zeroed() }
20    }
21  };
22  (@stub_fn $name:ident($($param:ident: $ptype:ty,)*)) => {
23    unsafe extern "C" fn $name($(_: $ptype,)*) {
24      eprintln!("Node-API symbol {} has not been loaded", stringify!($name));
25    }
26  };
27  (extern "C" {
28    $(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
29  }) => {
30    struct Napi {
31      $(
32        $name: unsafe extern "C" fn(
33          $($param: $ptype,)*
34        )$( -> $rtype)*,
35      )*
36    }
37
38    static mut NAPI: Napi = {
39      $(
40        generate!(@stub_fn $name($($param: $ptype,)*) $( -> $rtype)?);
41      )*
42
43      Napi {
44        $(
45          $name,
46        )*
47      }
48    };
49
50    #[allow(clippy::missing_safety_doc)]
51    pub unsafe fn load(
52      host: &libloading::Library,
53    ) -> Result<(), libloading::Error> {
54      NAPI = Napi {
55        $(
56          $name: {
57            let symbol: Result<libloading::Symbol<unsafe extern "C" fn ($(_: $ptype,)*)$( -> $rtype)*>, libloading::Error> = host.get(stringify!($name).as_bytes());
58            match symbol {
59              Ok(f) => *f,
60              Err(_) => {
61                // ignore error, use the stub function
62                NAPI.$name
63              }
64            }
65          },
66        )*
67      };
68
69      Ok(())
70    }
71
72    $(
73      #[inline]
74      #[allow(clippy::missing_safety_doc)]
75      pub unsafe fn $name($($param: $ptype,)*)$( -> $rtype)* {
76        (NAPI.$name)($($param,)*)
77      }
78    )*
79  };
80}
81
82#[cfg(any(
83  target_family = "wasm",
84  all(not(target_env = "msvc"), not(feature = "dyn-symbols"))
85))]
86macro_rules! generate {
87  (extern "C" {
88    $(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
89  }) => {
90    extern "C" {
91      $(
92        pub fn $name($($param: $ptype,)*)$( -> $rtype)*;
93      ) *
94    }
95  };
96}
97
98mod functions;
99mod types;
100
101pub use functions::*;
102pub use types::*;
103
104#[cfg(any(
105  target_env = "msvc",
106  all(not(target_family = "wasm"), feature = "dyn-symbols")
107))]
108/// Loads N-API symbols from host process.
109/// Must be called at least once before using any functions in bindings or
110/// they will panic
111///
112/// # Safety
113///
114/// The returned Library must be kept alive as long as any N-API
115pub unsafe fn setup() -> libloading::Library {
116  match load_all() {
117    Err(err) => panic!("{}", err),
118    Ok(l) => l,
119  }
120}