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