From db0f2304bef84f33e995be26dbf6d7c5f8b79085 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 14 Oct 2024 14:37:23 -0700 Subject: [PATCH 1/6] Use Rust 2021 edition --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) 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" From d8fbaf79db576a04b093c968b1bc0cc635f23d81 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 14 Oct 2024 16:50:15 -0700 Subject: [PATCH 2/6] Allow attributes in macro invocations Allows `#[cfg]` to be used to make certain definitions conditional. Such as for library version feature flags. --- src/lib.rs | 78 +++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4208b02..987dce1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -209,19 +209,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 +265,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 +296,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 +304,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 +312,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 +327,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 +359,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),+,)|* ); ); ); From 7ebedc86b7958cedc89535fb676e71178aa12952 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 16 Oct 2024 12:15:24 -0700 Subject: [PATCH 3/6] test: Add test for feature flag --- dlib-test/Cargo.toml | 5 ++++- dlib-test/src/lib.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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..0d1ebdf 100644 --- a/dlib-test/src/lib.rs +++ b/dlib-test/src/lib.rs @@ -3,6 +3,10 @@ use dlib::external_library; external_library!(Mlib, "m", functions: fn cos(f64) -> f64, + #[cfg(feature = "sin")] + fn sin(f64) -> f64, + #[cfg(feature = "nonexistant")] + fn nonexistant_function(f64) -> f64, ); #[cfg(feature = "dlopen")] @@ -20,5 +24,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()); } } From 11cb210af1c605049e81629ca12f120904929928 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 16 Oct 2024 12:39:02 -0700 Subject: [PATCH 4/6] Fixes for doc tests There is still a "local ambiguity when calling macro `external_library`" error. That appears to be a real bug. --- src/lib.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 987dce1..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"))] From 8c38e867bcc36a749c91322bfe68e7518168a4ae Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 16 Oct 2024 12:54:46 -0700 Subject: [PATCH 5/6] test: Add commented conditional statics/varargs Currently fails at macro expansion due to existing issue. --- dlib-test/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dlib-test/src/lib.rs b/dlib-test/src/lib.rs index 0d1ebdf..c4626be 100644 --- a/dlib-test/src/lib.rs +++ b/dlib-test/src/lib.rs @@ -1,12 +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")] From 69ed2c7c3662ff795485c16227958b92d947db6f Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Thu, 24 Oct 2024 09:31:48 -0700 Subject: [PATCH 6/6] ci: Test on Rust 1.56.0 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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