diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5332723..774bb2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - rust: ['1.40.0', 'stable', 'beta'] + rust: ['1.56.0', 'stable', 'beta'] runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 8aba6c5..f3be5f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ exclude = ["/dlib-test", "README.tpl"] readme = "README.md" keywords = ["dylib", "dlopen"] categories = ["api-bindings"] +edition = "2021" [dependencies] libloading = ">=0.7, <0.9" diff --git a/dlib-test/Cargo.toml b/dlib-test/Cargo.toml index f0b9697..b756949 100644 --- a/dlib-test/Cargo.toml +++ b/dlib-test/Cargo.toml @@ -10,4 +10,7 @@ dlib = { path = "../" } lazy_static = { version = "1.0", optional = true } [features] -"dlopen" = ["lazy_static"] \ No newline at end of file +default = ["sin"] +sin = [] +nonexistant = [] +dlopen = ["lazy_static"] diff --git a/dlib-test/src/lib.rs b/dlib-test/src/lib.rs index f9e4fdf..c4626be 100644 --- a/dlib-test/src/lib.rs +++ b/dlib-test/src/lib.rs @@ -1,8 +1,22 @@ use dlib::external_library; external_library!(Mlib, "m", + /* TODO: local ambiguity when calling macro + statics: + #[cfg(feature = "nonexistant")] + non_existant_static: f64, + */ functions: fn cos(f64) -> f64, + #[cfg(feature = "sin")] + fn sin(f64) -> f64, + #[cfg(feature = "nonexistant")] + fn nonexistant_function(f64) -> f64, + /* TODO: no rules expected this token in macro call + varargs: + #[cfg(feature = "nonexistant")] + fn nonexistant_varargs(f64 ...) -> f64, + */ ); #[cfg(feature = "dlopen")] @@ -20,5 +34,14 @@ mod tests { let angle = 1.8; let cosinus = unsafe { ffi_dispatch!(M_STATIC, cos, angle) }; assert_eq!(cosinus, angle.cos()); + + } + + #[cfg(feature = "sin")] + #[test] + fn invoke_sin() { + let angle = 1.8; + let sine = unsafe { ffi_dispatch!(M_STATIC, sin, angle) }; + assert_eq!(sine, angle.sin()); } } diff --git a/src/lib.rs b/src/lib.rs index 4208b02..8e3ff5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ //! dlib defines the `external_library!` macro, which can be invoked in this way: //! //! ```rust +//! # use dlib::external_library; +//! # use std::ffi::{c_float, c_int}; //! external_library!(feature="dlopen-foo", Foo, "foo", //! statics: //! me: c_int, @@ -28,7 +30,8 @@ //! this macro will expand to an extern block defining each of the items, using the third argument //! of the macro as a link name: //! -//! ```rust +//! ```rust no_run +//! # use std::ffi::{c_float, c_int, c_void}; //! #[link(name = "foo")] //! extern "C" { //! pub static me: c_int; @@ -47,6 +50,8 @@ //! and a method `open`, which tries to load the library from the name or path given as an argument. //! //! ```rust +//! # use dlib::DlError; +//! # use std::ffi::{c_float, c_int, c_void}; //! pub struct Foo { //! pub me: &'static c_int, //! pub you: &'static c_float, @@ -59,7 +64,10 @@ //! //! //! impl Foo { -//! pub unsafe fn open(name: &str) -> Result { /* ... */ } +//! pub unsafe fn open(name: &str) -> Result { +//! /* ... */ +//! # todo!() +//! } //! } //! ``` //! @@ -90,7 +98,9 @@ //! //! Then give the name of that feature as the `feature` argument to dlib's macros: //! -//! ```rust +//! ```rust no_run +//! # use dlib::external_library; +//! # use std::ffi::c_int; //! external_library!(feature="dlopen-foo", Foo, "foo", //! functions: //! fn foo() -> c_int, @@ -99,7 +109,12 @@ //! //! `dlib` provides helper macros to dispatch the access to foreign symbols: //! -//! ```rust +//! ```rust no_run +//! # use dlib::{ffi_dispatch, ffi_dispatch_static}; +//! # let arg1 = todo!(); +//! # let arg2 = todo!(); +//! # let function: fn(u32, u32) = todo!(); +//! # let my_static_var = todo!(); //! ffi_dispatch!(feature="dlopen-foo", Foo, function, arg1, arg2); //! ffi_dispatch_static!(feature="dlopen-foo", Foo, my_static_var); //! ``` @@ -122,6 +137,8 @@ //! Then, it can become as simple as putting this on top of all modules using the FFI: //! //! ```rust +//! # #![allow(unexpected_cfgs)] +//! # mod ffi {} //! #[cfg(feature = "dlopen-foo")] //! use ffi::FOO_STATIC; //! #[cfg(not(feature = "dlopen-foo"))] @@ -209,19 +226,22 @@ macro_rules! ffi_dispatch_static( #[macro_export] macro_rules! link_external_library( ($link: expr, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( #[link(name = $link)] extern "C" { $($( + $(#[$sattr])* pub static $sname: $stype; )+)* $($( + $(#[$fattr])* pub fn $fname($(_: $farg),*) -> $fret; )+)* $($( + $(#[$vattr])* pub fn $vname($(_: $vargs),+ , ...) -> $vret; )+)* } @@ -262,27 +282,30 @@ impl std::fmt::Display for DlError { #[macro_export] macro_rules! dlopen_external_library( (__struct, $structname: ident, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( pub struct $structname { __lib: $crate::Library, $($( + $(#[$sattr])* pub $sname: $crate::Symbol<'static, &'static $stype>, )+)* $($( + $(#[$fattr])* pub $fname: $crate::Symbol<'static, unsafe extern "C" fn($($farg),*) -> $fret>, )+)* $($( + $(#[$vattr])* pub $vname: $crate::Symbol<'static, unsafe extern "C" fn($($vargs),+ , ...) -> $vret>, )+)* } ); (__impl, $structname: ident, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( impl $structname { pub unsafe fn open(name: &str) -> Result<$structname, $crate::DlError> { @@ -290,7 +313,7 @@ macro_rules! dlopen_external_library( use std::mem::transmute; let lib = $crate::Library::new(name).map_err($crate::DlError::CantOpen)?; let s = $structname { - $($($sname: { + $($($(#[$sattr])* $sname: { let s_name = concat!(stringify!($sname), "\0"); transmute(match lib.get::<&'static $stype>(s_name.as_bytes()) { Ok(s) => s, @@ -298,7 +321,7 @@ macro_rules! dlopen_external_library( }) }, )+)* - $($($fname: { + $($($(#[$fattr])* $fname: { let s_name = concat!(stringify!($fname), "\0"); transmute(match lib.get:: $fret>(s_name.as_bytes()) { Ok(s) => s, @@ -306,7 +329,7 @@ macro_rules! dlopen_external_library( }) }, )+)* - $($($vname: { + $($($(#[$vattr])* $vname: { let s_name = concat!(stringify!($vname), "\0"); transmute(match lib.get:: $vret>(s_name.as_bytes()) { Ok(s) => s, @@ -321,19 +344,19 @@ macro_rules! dlopen_external_library( } ); ($structname: ident, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( $crate::dlopen_external_library!(__struct, - $structname, $(statics: $($sname: $stype),+,)|* - $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* - $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* + $structname, $(statics: $($(#[$sattr])* $sname: $stype),+,)|* + $(functions: $($(#[$fattr])* fn $fname($($farg),*) -> $fret),+,)|* + $(varargs: $($(#[$vattr])* fn $vname($($vargs),+) -> $vret),+,)|* ); $crate::dlopen_external_library!(__impl, - $structname, $(statics: $($sname: $stype),+,)|* - $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* - $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* + $structname, $(statics: $($(#[$sattr])* $sname: $stype),+,)|* + $(functions: $($(#[$fattr])* fn $fname($($farg),*) -> $fret),+,)|* + $(varargs: $($(#[$vattr])* fn $vname($($vargs),+) -> $vret),+,)|* ); unsafe impl Sync for $structname { } ); @@ -353,34 +376,34 @@ macro_rules! dlopen_external_library( #[macro_export] macro_rules! external_library( (feature=$feature: expr, $structname: ident, $link: expr, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( #[cfg(feature = $feature)] $crate::dlopen_external_library!( - $structname, $(statics: $($sname: $stype),+,)|* - $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* - $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* + $structname, $(statics: $($(#[$sattr])* $sname: $stype),+,)|* + $(functions: $($(#[$fattr])* fn $fname($($farg),*) -> $fret),+,)|* + $(varargs: $($(#[$vattr])* fn $vname($($vargs),+) -> $vret),+,)|* ); #[cfg(not(feature = $feature))] $crate::link_external_library!( - $link, $(statics: $($sname: $stype),+,)|* - $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* - $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* + $link, $(statics: $($(#[$sattr])* $sname: $stype),+,)|* + $(functions: $($(#[$fattr])* fn $fname($($farg),*) -> $fret),+,)|* + $(varargs: $($(#[$vattr])* fn $vname($($vargs),+) -> $vret),+,)|* ); ); ($structname: ident, $link: expr, - $(statics: $($sname: ident: $stype: ty),+,)|* - $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* - $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* + $(statics: $($(#[$sattr:meta])* $sname: ident: $stype: ty),+,)|* + $(functions: $($(#[$fattr:meta])* fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* + $(varargs: $($(#[$vattr:meta])* fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* ) => ( $crate::external_library!( feature="dlopen", $structname, $link, - $(statics: $($sname: $stype),+,)|* - $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* - $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* + $(statics: $($(#[$sattr])* $sname: $stype),+,)|* + $(functions: $($(#[$fattr])* fn $fname($($farg),*) -> $fret),+,)|* + $(varargs: $($(#[$vattr])* fn $vname($($vargs),+) -> $vret),+,)|* ); ); );