rust_libloading
rust_libloading copied to clipboard
support opening existing library
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.
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!
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?
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
:)
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:
- have open in windows accept an enum, telling it to either do a LoadLibraryEx or GetModuleHandleEx
- abstract the "opening" of existing library in a separate method - maybe
open_existing
?
Thoughts?
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.
I think this should be fixed by https://github.com/nagisa/rust_libloading/commit/8a0138d1025b35dbfca73db1326dac7cb122db95?
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.
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).
As I said before, though, I'm happy to accept at least a PR for the Windows side of this!