feat(napi-sys): support load Node-API symbols dynamically (#2014)

This commit is contained in:
LongYinan 2024-03-27 14:35:16 +08:00 committed by GitHub
parent 0550c56fcf
commit f2e5094345
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 74 additions and 68 deletions

View file

@ -548,7 +548,7 @@ jobs:
- name: Build
run: |
bun run build
bun run build:test
yarn workspace @examples/napi build --features dyn-symbols
- name: Test
continue-on-error: true
run: bun run test:bun

View file

@ -55,6 +55,7 @@ tokio_stats = ["tokio/stats"]
tokio_sync = ["tokio/sync"]
tokio_test_util = ["tokio/test-util"]
tokio_time = ["tokio/time"]
dyn-symbols = ["napi-sys/dyn-symbols"]
[dependencies]
bitflags = "2"

View file

@ -243,7 +243,7 @@ pub fn get_c_callback(raw_fn: ExportRegisterCallback) -> Result<crate::Callback>
})
}
#[cfg(all(windows, not(feature = "noop")))]
#[cfg(all(any(windows, feature = "dyn-symbols"), not(feature = "noop")))]
#[ctor::ctor]
fn load_host() {
unsafe {

View file

@ -12,6 +12,7 @@ rust-version = "1.65"
version = "2.3.0"
[features]
dyn-symbols = ["libloading"]
experimental = []
napi1 = []
napi2 = ["napi1"]
@ -26,5 +27,8 @@ napi9 = ["napi8"]
[package.metadata.workspaces]
independent = true
[target.'cfg(windows)'.dependencies.libloading]
version = "0.8"
[dependencies]
libloading = { version = "0.8", optional = true }
[target.'cfg(windows)'.dependencies]
libloading = "0.8"

View file

@ -780,15 +780,13 @@ pub use napi8::*;
#[cfg(feature = "napi9")]
pub use napi9::*;
#[cfg(windows)]
#[cfg(any(windows, feature = "dyn-symbols"))]
pub(super) unsafe fn load_all() -> Result<libloading::Library, libloading::Error> {
let host = match libloading::os::windows::Library::this() {
Ok(lib) => lib.into(),
Err(err) => {
eprintln!("Initialize libloading failed {}", err);
return Err(err);
}
};
#[cfg(windows)]
let host = libloading::os::windows::Library::this()?.into();
#[cfg(unix)]
let host = libloading::os::unix::Library::this().into();
napi1::load(&host)?;
#[cfg(feature = "napi2")]

View file

@ -1,6 +1,8 @@
// borrowed from https://github.com/neon-bindings/neon/tree/main/crates/neon/src/sys/bindings
#![allow(ambiguous_glob_reexports)]
#[cfg(windows)]
#[cfg(any(windows, feature = "dyn-symbols"))]
macro_rules! generate {
(extern "C" {
$(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
@ -15,7 +17,7 @@ macro_rules! generate {
#[inline(never)]
fn panic_load<T>() -> T {
panic!("Must load N-API bindings")
panic!("Node-API symbol has not been loaded")
}
static mut NAPI: Napi = {
@ -43,11 +45,10 @@ macro_rules! generate {
match symbol {
Ok(f) => *f,
Err(e) => {
debug_assert!({
println!("Load Node-API [{}] from host runtime failed: {}", stringify!($name), e);
true
});
return Ok(());
#[cfg(debug_assertions)] {
eprintln!("Load Node-API [{}] from host runtime failed: {}", stringify!($name), e);
}
NAPI.$name
}
}
},
@ -67,7 +68,7 @@ macro_rules! generate {
};
}
#[cfg(not(windows))]
#[cfg(not(any(windows, feature = "dyn-symbols")))]
macro_rules! generate {
(extern "C" {
$(fn $name:ident($($param:ident: $ptype:ty$(,)?)*)$( -> $rtype:ty)?;)+
@ -90,7 +91,7 @@ pub use types::*;
/// Must be called at least once before using any functions in bindings or
/// they will panic.
/// Safety: `env` must be a valid `napi_env` for the current thread
#[cfg(windows)]
#[cfg(any(windows, feature = "dyn-symbols"))]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn setup() -> libloading::Library {
match load_all() {

View file

@ -11,6 +11,7 @@ crate-type = ["cdylib"]
[features]
latest = ["napi/napi9"]
napi3 = ["napi/napi3"]
dyn-symbols = ["napi/dyn-symbols"]
[dependencies]
futures = "0.3"

View file

@ -10,6 +10,7 @@ crate-type = ["cdylib"]
[features]
snmalloc = ["snmalloc-rs"]
dyn-symbols = ["napi/dyn-symbols"]
[dependencies]
chrono = "0.4"