rust_libloading icon indicating copy to clipboard operation
rust_libloading copied to clipboard

support opening existing library

Open yuval-k opened this issue 7 years ago • 9 comments

Hello,

Currently you can do Library::new() which loads a library. For my use case it would be create to have Library::open that opens an already existing library.

  • I'm trying to query optionally exported functions in preloaded shared library.

Implementation can be accomplished with the RTLD_NOLOAD flag for dlopen on most unixes and GetModuleHandleEx in windows.

I can write the code myself and submit a PR if that works for you.

yuval-k avatar Jun 22 '17 12:06 yuval-k

Is using OS-specific open with appropriate flags not good enough?

Windows is more tricky. I did not implement open for it specifically because I found GetModuleHandleEx to be extremely difficult to adapt to be more similar to the behaviour of the unix open. It is almost entirely different thing.

That being said, I would gladly take a PR that adds an open method to the windows’ Library with SOME semantics. It is a platform-specific module after all!

nagisa avatar Jun 22 '17 12:06 nagisa

I'm trying to add support for optional functions in rust jack (audio connection kit) bindings. and since jack is available for windows a cross platform solution is preferred..

My plan was to add an "open" method that does dlopen(... | RTLD_NOLOAD) and GetModuleHandleEx(0, modulename, ...)

as far as i can see, semantics are similar: both functions will return a handle that lets us find symbols, and increase the library ref-count - can you elaborate on the difficulties you mention?

yuval-k avatar Jun 22 '17 13:06 yuval-k

I do not exactly remember the exact difference. Besides it is fairly trivial to implement opening exactly the way you want it in library:

#[cfg(windows)]
fn my_open(..) -> Result<libloading::Library> {
    libloading::Library::from(libloading::os::windows::Library::open(...)?)
}
#[cfg(not(windows))]
fn my_open(..) -> Result<libloading::Library> {
    libloading::Library::from(libloading::os::unix::Library::open(...)?)
}

This seems fairly concise to me and does not run into the problem where the flag combination to the underlying call to OS is not quite what they need for their exact use case. All we really need is the implementation of libloading::os::windows::Library::open :)

nagisa avatar Jun 22 '17 14:06 nagisa

I think it maybe confusing to implement open for windows.

For unix, open always calls for dlopen. but in windows, if we want to load a new library, we have to call LoadLibrary. and if we want to open an existing one we call GetModuleHandleEx.

I have 2 thoughts on how to address this:

  1. have open in windows accept an enum, telling it to either do a LoadLibraryEx or GetModuleHandleEx
  2. abstract the "opening" of existing library in a separate method - maybe open_existing?

Thoughts?

yuval-k avatar Jun 23 '17 00:06 yuval-k

LoadLibraryEx will just increment a reference count if the library is already loaded, just like dlopen does. There’s no point in using GetModuleHandleEx at all IMO.

nagisa avatar Sep 24 '17 08:09 nagisa

I think this should be fixed by https://github.com/nagisa/rust_libloading/commit/8a0138d1025b35dbfca73db1326dac7cb122db95?

yorickpeterse avatar Sep 25 '20 14:09 yorickpeterse

So I happened to need this in my project and I think there's a misunderstanding here?

What I currently need (and what I believe the issue is about) is a method Library::open_if_already_loaded(name) that:

  • if the library is already loaded in the current process, returns it;
  • if the library is not loaded in the current process, does not load it (so just returns None/Err).

This can be accomplished with dlopen(name, ... | RTLD_NOLOAD) and with GetModuleHandleEx(0, name, ...).

https://github.com/nagisa/rust_libloading/commit/8a0138d1025b35dbfca73db1326dac7cb122db95 adds a method to get the handle to the calling library itself, which is not really related.

YaLTeR avatar Dec 30 '20 08:12 YaLTeR

Yeah, sorry, my bad.

RTLD_NOLOAD is a glibc-specific extension that has propagated to some other targets, but not all of them. As thus this Library::open_if_already_loaded cannot get implemented on systems where this or an equivalent functionality is not available (e.g. OpenBSD).

nagisa avatar Dec 30 '20 11:12 nagisa

As I said before, though, I'm happy to accept at least a PR for the Windows side of this!

nagisa avatar Dec 30 '20 11:12 nagisa