-
Notifications
You must be signed in to change notification settings - Fork 287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamic loading sample #645
Changes from 3 commits
2791076
d7dd0fa
b3c7aca
63358f5
39a828e
6ce7cf0
9485d9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,16 +5,20 @@ authors = ["Dave Herman <[email protected]>"] | |
description = "Bindings to the Node.js native addon API, used by the Neon implementation." | ||
repository = "https://github.com/neon-bindings/neon" | ||
license = "MIT/Apache-2.0" | ||
edition = "2018" | ||
|
||
[dependencies] | ||
cfg-if = "0.1.9" | ||
libloading = { version = "0.6.5", optional = true } | ||
lazy_static = { version = "1.4.0", optional = true } | ||
neon-sys = { version = "=0.5.3", path = "../neon-sys", optional = true } | ||
nodejs-sys = { version = "0.7.0", optional = true } | ||
smallvec = "1.4.2" | ||
|
||
[features] | ||
default = [] | ||
docs-only = ["neon-sys/docs-only"] | ||
napi = ["nodejs-sys", "lazy_static", "libloading"] | ||
|
||
[package.metadata.docs.rs] | ||
features = ["docs-only"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
use raw::{Env, Local}; | ||
use crate::raw::{Env, Local}; | ||
use std::os::raw::c_void; | ||
use std::ptr::null_mut; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
use std::mem::MaybeUninit; | ||
use lazy_static::lazy_static; | ||
use libloading::{Library, Symbol}; | ||
|
||
/* Later we should do: | ||
#[repr(C)] | ||
struct NapiEnvStruct {} | ||
|
||
#[repr(C)] | ||
struct NapiValueStruct {} | ||
|
||
pub(crate) type NapiEnv = *mut NapiEnvStruct; | ||
pub(crate) type NapiValue = *mut NapiValueStruct; | ||
|
||
But in this sample we still rely on nodejs_sys's types | ||
*/ | ||
|
||
pub(crate) type NapiEnv = nodejs_sys::napi_env; | ||
pub(crate) type NapiValue = nodejs_sys::napi_value; | ||
|
||
#[repr(C)] | ||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
#[allow(non_camel_case_types)] | ||
#[allow(dead_code)] | ||
pub(crate) enum NapiStatus { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy-paste from the N-API docs; with |
||
napi_ok, | ||
napi_invalid_arg, | ||
napi_object_expected, | ||
napi_string_expected, | ||
napi_name_expected, | ||
napi_function_expected, | ||
napi_number_expected, | ||
napi_boolean_expected, | ||
napi_array_expected, | ||
napi_generic_failure, | ||
napi_pending_exception, | ||
napi_cancelled, | ||
napi_escape_called_twice, | ||
napi_handle_scope_mismatch, | ||
napi_callback_scope_mismatch, | ||
napi_queue_full, | ||
napi_closing, | ||
napi_bigint_expected, | ||
napi_date_expected, | ||
napi_arraybuffer_expected, | ||
napi_detachable_arraybuffer_expected, | ||
napi_would_deadlock, | ||
} | ||
|
||
pub(crate) struct Napi<'a> { | ||
pub napi_get_undefined: Symbol<'a, unsafe extern "C" fn(env: NapiEnv, out: *mut NapiValue) -> NapiStatus>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the actual declaration is quite hard to read here, because of the |
||
pub napi_get_null: Symbol<'a, unsafe extern "C" fn(env: NapiEnv, out: *mut NapiValue) -> NapiStatus>, | ||
|
||
pub napi_get_boolean: | ||
Symbol<'a, unsafe extern "C" fn(env: NapiEnv, value: bool, out: *mut NapiValue) -> NapiStatus>, | ||
pub napi_get_value_bool: | ||
Symbol<'a, unsafe extern "C" fn(env: NapiEnv, value: NapiValue, out: *mut bool) -> NapiStatus>, | ||
|
||
pub napi_create_double: | ||
Symbol<'a, unsafe extern "C" fn(env: NapiEnv, value: f64, out: *mut NapiValue) -> NapiStatus>, | ||
pub napi_get_value_double: | ||
Symbol<'a, unsafe extern "C" fn(env: NapiEnv, value: NapiValue, out: *mut f64) -> NapiStatus>, | ||
} | ||
|
||
#[cfg(not(windows))] | ||
fn get_host_library() -> Library { | ||
use libloading::os::unix::Library; | ||
Library::this().into() | ||
} | ||
|
||
#[cfg(windows)] | ||
fn get_host_library() -> Library { | ||
use libloading::os::windows::Library; | ||
Library::this().into() | ||
} | ||
|
||
lazy_static! { | ||
static ref HOST: Library = get_host_library(); | ||
} | ||
|
||
impl Napi<'_> { | ||
fn try_from_host() -> Result<Self, libloading::Error> { | ||
let host = &HOST; | ||
|
||
Ok(unsafe { | ||
Self { | ||
napi_get_undefined: host.get(b"napi_get_undefined")?, | ||
napi_get_null: host.get(b"napi_get_null")?, | ||
napi_get_boolean: host.get(b"napi_get_boolean")?, | ||
napi_get_value_bool: host.get(b"napi_get_value_bool")?, | ||
napi_create_double: host.get(b"napi_create_double")?, | ||
napi_get_value_double: host.get(b"napi_get_value_double")?, | ||
} | ||
}) | ||
} | ||
|
||
pub fn from_host() -> Self { | ||
Self::try_from_host().unwrap() | ||
} | ||
} | ||
|
||
pub(crate) static mut NAPI: MaybeUninit<Napi> = MaybeUninit::uninit(); | ||
|
||
/// Load the N-API symbols we need. | ||
pub(crate) unsafe fn load() { | ||
NAPI.as_mut_ptr().write(Napi::from_host()); | ||
} | ||
|
||
macro_rules! napi { | ||
( $name:ident ( $($args:expr),* ) ) => { | ||
{ | ||
let bindings = $crate::napi::bindings::NAPI.as_ptr(); | ||
let result: $crate::napi::bindings::NapiStatus = ((*bindings).$name)( | ||
$($args),* | ||
); | ||
result | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
use raw::{Env, Local}; | ||
use crate::raw::{Env, Local}; | ||
use std::os::raw::c_void; | ||
use std::ptr::null_mut; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
use std::mem::MaybeUninit; | ||
|
||
use raw::{Env, Local}; | ||
use crate::raw::{Env, Local}; | ||
|
||
use nodejs_sys as napi; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
use raw::Local; | ||
use crate::raw::Local; | ||
|
||
pub unsafe extern "C" fn same_handle(_h1: Local, _h2: Local) -> bool { unimplemented!() } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
use raw::{Env, Local}; | ||
use crate::raw::{Env, Local}; | ||
|
||
use nodejs_sys as napi; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to edition 2018 because I only know how to use
macro_rules!
in this edition