Skip to content

Commit d707c75

Browse files
authored
Merge pull request #13 from milkey-mouse/parametrized-feature-name
Parametrize dlopen feature names
2 parents 39c1a48 + c1550f2 commit d707c75

File tree

3 files changed

+84
-62
lines changed

3 files changed

+84
-62
lines changed

Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,5 @@ authors = ["Victor Berger <victor.berger@m4x.org>"]
66
license = "MIT"
77
description = "Helper macros for handling manually loading optional system libraries."
88

9-
109
[dependencies]
1110
libloading = "0.6"
12-
13-
[features]
14-
dlopen = []

README.md

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@
33
[![](http://meritbadge.herokuapp.com/dlib)](https://crates.io/crates/dlib)
44
[![Docs.rs](https://docs.rs/dlib/badge.svg)](https://docs.rs/dlib)
55

6-
dlib is a small crate providing macros to make easy the use of external system libraries
7-
that can or cannot be optionally loaded at runtime, depending on whether the `dlopen` cargo
8-
feature is enabled.
6+
dlib is a small crate providing macros to make easy the use of external system libraries that
7+
can or cannot be optionally loaded at runtime, depending on whether a certain feature is enabled.
98

109
## Usage
1110

12-
dlib defines the `external_library!` macro, which can be invoked with way:
11+
dlib defines the `external_library!` macro, which can be invoked in this way:
1312

1413
```rust
15-
external_library!(Foo, "foo",
14+
external_library!(feature="dlopen-foo", Foo, "foo",
1615
statics:
1716
me: c_int,
1817
you: c_float,
@@ -30,8 +29,9 @@ As you can see, it is required to separate static values from functions and from
3029
having variadic arguments. Each of these 3 categories is optional, but the ones used must appear
3130
in this order. Return types of the functions must all be explicit (hence `-> ()` for void functions).
3231

33-
If the feature `dlopen` is absent, this macro will expand to an extern block defining each of the
34-
items, using the second argument of the macro as a link name:
32+
If the feature named by the `feature` argument (in this example, `dlopen-foo`) is absent on your crate,
33+
this macro will expand to an extern block defining each of the items, using the third argument
34+
of the macro as a link name:
3535

3636
```rust
3737
#[link(name = "foo")]
@@ -47,9 +47,9 @@ extern "C" {
4747

4848
```
4949

50-
If the feature `dlopen` is present, it will expand to a `struct` named by the first argument of the macro,
51-
with one field for each of the symbols defined, and a method `open`, which tries to load the library
52-
from the name or path given as argument
50+
If the feature named by the `feature` argument is present on your crate, it will expand to a
51+
`struct` named by the second argument of the macro, with one field for each of the symbols defined;
52+
and a method `open`, which tries to load the library from the name or path given as an argument.
5353

5454
```rust
5555
pub struct Foo {
@@ -73,37 +73,57 @@ with all of its fields pointing to the appropriate symbol.
7373

7474
If the library specified by `name` could not be found, it returns `Err(DlError::NotFount)`.
7575

76-
It will also fail on the first missing symbol, with `Err(DlError::MissingSymbol(symb))` where `symb` is a `&str`
77-
containing the missing symbol name.
76+
It will also fail on the first missing symbol, with `Err(DlError::MissingSymbol(symb))` where `symb`
77+
is a `&str` containing the missing symbol name.
7878

7979
## Remaining generic in your crate
8080

81-
If you want your crate to remain generic over the `dlopen` cargo feature, simply add this to your `Cargo.toml`
81+
If you want your crate to remain generic over dlopen vs. linking, simply add a feature to your `Cargo.toml`:
8282

83-
```
83+
```toml
8484
[dependencies]
85-
dlib = "0.2"
85+
dlib = "0.5"
8686

8787
[features]
88-
dlopen = ["dlib/dlopen"]
88+
dlopen-foo = []
8989
```
9090

91-
And the library also provides helper macros to dispatch the access to foreign symbols:
91+
Then give the name of that feature as the `feature` argument to dlib's macros:
9292

9393
```rust
94-
ffi_dispatch!(Foo, function, arg1, arg2);
95-
ffi_dispatch_static!(Foo, static);
94+
external_library!(feature="dlopen-foo", Foo, "foo",
95+
functions:
96+
fn foo() -> c_int,
97+
);
9698
```
9799

98-
These will expand to the appropriate value or function call depending on the presence of the `dlopen` feature.
100+
`dlib` provides helper macros to dispatch the access to foreign symbols:
101+
102+
```rust
103+
ffi_dispatch!(feature="dlopen-foo", Foo, function, arg1, arg2);
104+
ffi_dispatch_static!(feature="dlopen-foo", Foo, my_static_var);
105+
```
106+
107+
These will expand to the appropriate value or function call depending on the presence or absence of the
108+
`dlopen-foo` feature on your crate.
109+
110+
You must still ensure that the functions/statics or the wrapper struct `Foo` are in scope. For example,
111+
you could use the [`lazy_static`](https://crates.io/crates/lazy_static) crate to do the initialization,
112+
and store the wrapper struct in a static variable that you import wherever needed:
113+
114+
```rust
115+
#[cfg(feature = "dlopen-foo")]
116+
lazy_static::lazy_static! {
117+
pub static ref FOO_STATIC: Foo =
118+
Foo::open("libfoo.so").ok().expect("could not find libfoo");
119+
}
120+
```
99121

100-
You must still ensure that the functions/statics or the wrapper struct `Foo` are in scope. A simple pattern would be
101-
for example to use the `lazy_static!` crate to do the initialization and store the wrapper struct in a static, that you then
102-
just need to import everywhere needed. Then, it can become as simple as putting this on top of all modules using the FFI:
122+
Then, it can become as simple as putting this on top of all modules using the FFI:
103123

104124
```rust
105-
#[cfg(features = "dlopen")]
125+
#[cfg(feature = "dlopen-foo")]
106126
use ffi::FOO_STATIC;
107-
#[cfg(not(features = "dlopen"))]
127+
#[cfg(not(feature = "dlopen-foo"))]
108128
use ffi::*;
109129
```

src/lib.rs

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,39 @@ extern crate libloading;
22

33
pub use libloading::{Library, Symbol};
44

5-
#[cfg(feature = "dlopen")]
65
#[macro_export]
76
macro_rules! ffi_dispatch(
8-
($handle: ident, $func: ident, $($arg: expr),*) => (
9-
($handle.$func)($($arg),*)
10-
)
11-
);
7+
(feature=$feature: expr, $handle: ident, $func: ident, $($arg: expr),*) => (
8+
{
9+
#[cfg(feature = $feature)]
10+
let ret = ($handle.$func)($($arg),*);
11+
#[cfg(not(feature = $feature))]
12+
let ret = $func($($arg),*);
1213

13-
#[cfg(not(feature = "dlopen"))]
14-
#[macro_export]
15-
macro_rules! ffi_dispatch(
14+
ret
15+
}
16+
);
1617
($handle: ident, $func: ident, $($arg: expr),*) => (
17-
$func($($arg),*)
18-
)
18+
// NOTE: this "dlopen" refers to a feature on the crate *using* dlib
19+
$crate::ffi_dispatch!(feature="dlopen", $handle, $func, $($arg),*)
20+
);
1921
);
2022

21-
#[cfg(feature = "dlopen")]
2223
#[macro_export]
2324
macro_rules! ffi_dispatch_static(
24-
($handle: ident, $name: ident) => (
25-
$handle.$name
26-
)
27-
);
25+
(feature=$feature: expr, $handle: ident, $name: ident) => (
26+
{
27+
#[cfg(feature = $feature)]
28+
let ret = $handle.$name;
29+
#[cfg(not(feature = $feature))]
30+
let ret = &$name;
2831

29-
#[cfg(not(feature = "dlopen"))]
30-
#[macro_export]
31-
macro_rules! ffi_dispatch_static(
32-
($handle: ident, $name: ident) => (
33-
&$name
34-
)
32+
ret
33+
}
34+
);
35+
($handle:ident, $name: ident) => (
36+
$crate::ffi_dispatch_static!(feature="dlopen", $handle, $name)
37+
);
3538
);
3639

3740
#[macro_export]
@@ -132,12 +135,12 @@ macro_rules! dlopen_external_library(
132135
$(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
133136
$(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
134137
) => (
135-
dlopen_external_library!(__struct,
138+
$crate::dlopen_external_library!(__struct,
136139
$structname, $(statics: $($sname: $stype),+,)|*
137140
$(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
138141
$(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
139142
);
140-
dlopen_external_library!(__impl,
143+
$crate::dlopen_external_library!(__impl,
141144
$structname, $(statics: $($sname: $stype),+,)|*
142145
$(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
143146
$(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
@@ -146,32 +149,35 @@ macro_rules! dlopen_external_library(
146149
);
147150
);
148151

149-
#[cfg(not(feature = "dlopen"))]
150152
#[macro_export]
151153
macro_rules! external_library(
152-
($structname: ident, $link: expr,
154+
(feature=$feature: expr, $structname: ident, $link: expr,
153155
$(statics: $($sname: ident: $stype: ty),+,)|*
154156
$(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
155157
$(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
156158
) => (
157-
link_external_library!(
159+
#[cfg(feature = $feature)]
160+
$crate::dlopen_external_library!(
161+
$structname, $(statics: $($sname: $stype),+,)|*
162+
$(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
163+
$(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
164+
);
165+
166+
#[cfg(not(feature = $feature))]
167+
$crate::link_external_library!(
158168
$link, $(statics: $($sname: $stype),+,)|*
159169
$(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
160170
$(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
161171
);
162172
);
163-
);
164-
165-
#[cfg(feature = "dlopen")]
166-
#[macro_export]
167-
macro_rules! external_library(
168173
($structname: ident, $link: expr,
169174
$(statics: $($sname: ident: $stype: ty),+,)|*
170175
$(functions: $(fn $fname: ident($($farg: ty),*) -> $fret:ty),+,)|*
171176
$(varargs: $(fn $vname: ident($($vargs: ty),+) -> $vret: ty),+,)|*
172177
) => (
173-
dlopen_external_library!(
174-
$structname, $(statics: $($sname: $stype),+,)|*
178+
$crate::external_library!(
179+
feature="dlopen", $structname, $link,
180+
$(statics: $($sname: $stype),+,)|*
175181
$(functions: $(fn $fname($($farg),*) -> $fret),+,)|*
176182
$(varargs: $(fn $vname($($vargs),+) -> $vret),+,)|*
177183
);

0 commit comments

Comments
 (0)