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