|
127 | 127 | //! #[cfg(not(feature = "dlopen-foo"))] |
128 | 128 | //! use ffi::*; |
129 | 129 | //! ``` |
| 130 | +//! |
| 131 | +//! Alternatively to using `ffi_dispatch!` and `ffi_dispatch_static!` or directly calling |
| 132 | +//! module-level functions in non-dlopen code, you can use the dlopen-style API (ie. `Foo::open`) |
| 133 | +//! on non-dlopen builds. This allows using the same API regardless of whether the `dlopen-foo` |
| 134 | +//! feature flag is set. To enable this, use `external_library_universal!` instead of |
| 135 | +//! `external_library!`. |
| 136 | +//! |
| 137 | +//! ```rust |
| 138 | +//! external_library_universal!(feature="dlopen-foo", Foo, "foo", |
| 139 | +//! functions: |
| 140 | +//! fn foo() -> c_int, |
| 141 | +//! ); |
| 142 | +//! |
| 143 | +//! // This works both with and without dlopen-foo. The argument to `File::open` is ignored in |
| 144 | +//! // non-dlopen builds, and the function can fail only on dlopen builds. |
| 145 | +//! lazy_static::lazy_static! { |
| 146 | +//! pub static ref FOO_STATIC: Foo = |
| 147 | +//! Foo::open("libfoo.so").ok().expect("couldn ot find libfoo"); |
| 148 | +//! } |
| 149 | +//! ``` |
130 | 150 | #![warn(missing_docs)] |
131 | 151 |
|
132 | 152 | extern crate libloading; |
@@ -228,6 +248,71 @@ macro_rules! link_external_library( |
228 | 248 | ); |
229 | 249 | ); |
230 | 250 |
|
| 251 | +#[doc(hidden)] |
| 252 | +#[macro_export] |
| 253 | +macro_rules! link_external_library_dlopen_compat( |
| 254 | + (__struct, $structname: ident, |
| 255 | + $(statics: $($sname: ident: $stype: ty),+,)|* |
| 256 | + $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
| 257 | + $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* |
| 258 | + ) => ( |
| 259 | + pub struct $structname { |
| 260 | + $($( |
| 261 | + pub $sname: &'static $stype, |
| 262 | + )+)* |
| 263 | + $($( |
| 264 | + pub $fname: unsafe extern "C" fn($($farg),*) -> $fret, |
| 265 | + )+)* |
| 266 | + $($( |
| 267 | + pub $vname: unsafe extern "C" fn($($vargs),+ , ...) -> $vret, |
| 268 | + )+)* |
| 269 | + } |
| 270 | + ); |
| 271 | + (__impl, $structname: ident, |
| 272 | + $(statics: $($sname: ident: $stype: ty),+,)|* |
| 273 | + $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
| 274 | + $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* |
| 275 | + ) => ( |
| 276 | + impl $structname { |
| 277 | + pub unsafe fn open(_name: &str) -> Result<$structname, $crate::DlError> { |
| 278 | + // we use it to ensure the 'static lifetime |
| 279 | + use std::mem::transmute; |
| 280 | + Ok($structname { |
| 281 | + $($($sname: { |
| 282 | + $sname |
| 283 | + }, |
| 284 | + )+)* |
| 285 | + $($($fname: { |
| 286 | + $fname |
| 287 | + }, |
| 288 | + )+)* |
| 289 | + $($($vname: { |
| 290 | + transmute($vname) |
| 291 | + }, |
| 292 | + )+)* |
| 293 | + }) |
| 294 | + } |
| 295 | + } |
| 296 | + ); |
| 297 | + ($structname: ident, |
| 298 | + $(statics: $($sname: ident: $stype: ty),+,)|* |
| 299 | + $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
| 300 | + $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* |
| 301 | + ) => ( |
| 302 | + $crate::link_external_library_dlopen_compat!(__struct, |
| 303 | + $structname, $(statics: $($sname: $stype),+,)|* |
| 304 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 305 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 306 | + ); |
| 307 | + $crate::link_external_library_dlopen_compat!(__impl, |
| 308 | + $structname, $(statics: $($sname: $stype),+,)|* |
| 309 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 310 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 311 | + ); |
| 312 | + unsafe impl Sync for $structname { } |
| 313 | + ); |
| 314 | +); |
| 315 | + |
231 | 316 | /// An error generated when failing to load a library |
232 | 317 | #[derive(Debug)] |
233 | 318 | pub enum DlError { |
@@ -371,6 +456,59 @@ macro_rules! external_library( |
371 | 456 | $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
372 | 457 | ); |
373 | 458 | ); |
| 459 | + ($structname: ident, $link: expr, |
| 460 | + $(statics: $($sname: ident: $stype: ty),+,)|* |
| 461 | + $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
| 462 | + $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* |
| 463 | + ) => ( |
| 464 | + $crate::external_library!( feature="dlopen", $structname, $link, |
| 465 | + $(statics: $($sname: $stype),+,)|* |
| 466 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 467 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 468 | + ); |
| 469 | + ); |
| 470 | +); |
| 471 | + |
| 472 | +/// Main macro of this library, used to generate the the FFI bindings that are universal in both |
| 473 | +/// dlopen and non-dlopen form. |
| 474 | +/// |
| 475 | +/// The expected arguments are, in order: |
| 476 | +/// - (Optional) The name of the cargo feature conditioning the usage of dlopen, in the form |
| 477 | +/// `feature="feature-name"`. If ommited, the feature `"dlopen"` will be used. |
| 478 | +/// - The name of the struct that will be generated when the dlopen-controlling feature is |
| 479 | +/// enabled |
| 480 | +/// - The link name of the target library |
| 481 | +/// - The desctription of the statics, functions, and vararg functions that should be linked |
| 482 | +/// |
| 483 | +/// See crate-level documentation for a detailed example of use. |
| 484 | +#[macro_export] |
| 485 | +macro_rules! external_library_universal( |
| 486 | + (feature=$feature: expr, $structname: ident, $link: expr, |
| 487 | + $(statics: $($sname: ident: $stype: ty),+,)|* |
| 488 | + $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
| 489 | + $(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|* |
| 490 | + ) => ( |
| 491 | + #[cfg(feature = $feature)] |
| 492 | + $crate::dlopen_external_library!( |
| 493 | + $structname, $(statics: $($sname: $stype),+,)|* |
| 494 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 495 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 496 | + ); |
| 497 | + |
| 498 | + #[cfg(not(feature = $feature))] |
| 499 | + $crate::link_external_library!( |
| 500 | + $link, $(statics: $($sname: $stype),+,)|* |
| 501 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 502 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 503 | + ); |
| 504 | + |
| 505 | + #[cfg(not(feature = $feature))] |
| 506 | + $crate::link_external_library_dlopen_compat!( |
| 507 | + $structname, $(statics: $($sname: $stype),+,)|* |
| 508 | + $(functions: $(fn $fname($($farg),*) -> $fret),+,)|* |
| 509 | + $(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|* |
| 510 | + ); |
| 511 | + ); |
374 | 512 | ($structname: ident, $link: expr, |
375 | 513 | $(statics: $($sname: ident: $stype: ty),+,)|* |
376 | 514 | $(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|* |
|
0 commit comments