dlib icon indicating copy to clipboard operation
dlib copied to clipboard

Remove the need for the “Remaining generic in your crate” paragraph in the README?

Open Ekleog opened this issue 5 years ago • 3 comments

Random drive-by thought: if external_library generated code like this when not having the dlopen feature:

mod private {
    #[link(name = "foo")]
    extern "C" {
        static me: c_int;
        static you: c_float;
        fn foo() -> c_int;
        fn bar(_: c_int, _: c_float) -> ();
        fn baz(_: *const c_int) -> c_int;
        fn blah(_: c_int, _: c_int, ...) -> *const c_void;
        fn bleh(_: c_int, ...) -> ();
   }

   pub struct Foo {
       pub me: &'static c_int,
       pub you: &'static c_float,
       pub foo: unsafe extern "C" fn() -> c_int,
       pub bar: unsafe extern "C" fn(c_int, c_float) -> (),
       pub baz: unsafe extern "C" fn(*const c_int) -> c_int,
       pub blah: unsafe extern "C" fn(c_int, c_int, ...) -> *const c_void,
       pub bleh: unsafe extern "C" fn(c_int, ...) -> (),
    }

    impl Foo {
        pub fn open(_: Option<&str>) -> Result<Foo, DlError> { /* ... */ }
    }
}
use private::Foo;

Then the user could just always use Foo::open(find_solib_or_none("foo.so")).foo(), without having to care about the dlopen feature?

It'd probably also reduce a bit the issue with the dlopen feature, which is that currently it's not additive.

That said it would still not really be, but if Foo::open(None) with the dlopen feature searched in the so path… then maybe it'd actually become kind of additive? (still not perfectly so, but at least for all reasonable users that either pass a valid Some(lib) or None it'd be)

Ekleog avatar Jul 03 '20 23:07 Ekleog

Actually, giving it a second thought… with such a change, I think that staticlib (that bakes in the solib from compile-time) would actually be an additive feature (ignoring the argument and always returning a valid Foo is always strictly better than trying to dlopen)

The drawback of switching to it being, that it's AFAIK not possible to say “we need this dependency iff staticlib is not enabled”, which would mean that libloading would then always become a dependency, which would just not be used when staticlib is enabled. So… pros and cons, I guess :)

Ekleog avatar Jul 04 '20 19:07 Ekleog

That's an interesting idea. :)

One other drawback though, is that currently the generated struct when using the dlopen feature apparently takes a lot of space, see https://github.com/Smithay/wayland-rs/issues/275

Not sure generalizing that to be always the case would be a super nice thing.

elinorbgr avatar Jul 05 '20 08:07 elinorbgr

Hmm… Then maybe generating a struct like this would be better?

mod private {
    #[link(name = "foo")]
    extern "C" {
        static me: c_int;
        static you: c_float;
        fn foo() -> c_int;
        fn bar(_: c_int, _: c_float) -> ();
        fn baz(_: *const c_int) -> c_int;
        fn blah(_: c_int, _: c_int, ...) -> *const c_void;
        fn bleh(_: c_int, ...) -> ();
   }

   pub struct Foo(());

   impl Foo {
       pub fn open(_: Option<&str>) -> Result<Foo, DlError> { /* ... */ }

       #[inline] pub fn me(&self) -> &'static c_int { me }
       #[inline] pub fn you(&self) -> &'static c_float { you }
       #[inline] pub fn foo(&self) -> unsafe extern "C" fn() -> c_int { foo }
       #[inline] pub fn bar(&self) -> unsafe extern "C" fn(c_int, c_float) -> () { bar }
       #[inline] pub fn baz(&self) -> unsafe extern "C" fn(*const c_int) -> c_int { baz }
       #[inline] pub fn blah(&self) -> unsafe extern "C" fn(c_int, c_int, ...) -> *const c_void { blah }
       #[inline] pub fn bleh(&self) -> unsafe extern "C" fn(c_int, ...) -> () { bleh }
   }
}
use private::Foo;

This way the struct would be zero-sized when static-linking, the ergonomic cost then being just adding parenthesis after field access. What do you think about it?

(disclaimer: I'm not sure whether me and you should be unsafe or if open should, but it feels like at least one of these should be, in order to have the same API as the dlopen use case, so… probably open?)

Ekleog avatar Jul 05 '20 09:07 Ekleog