Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support opening existing library #27

Open
yuval-k opened this issue Jun 22, 2017 · 9 comments
Open

support opening existing library #27

yuval-k opened this issue Jun 22, 2017 · 9 comments

Comments

@yuval-k
Copy link

yuval-k commented Jun 22, 2017

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.

@nagisa
Copy link
Owner

nagisa commented Jun 22, 2017

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!

@yuval-k
Copy link
Author

yuval-k commented Jun 22, 2017

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?

@nagisa
Copy link
Owner

nagisa commented Jun 22, 2017

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 :)

@yuval-k
Copy link
Author

yuval-k commented Jun 23, 2017

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?

@nagisa
Copy link
Owner

nagisa commented Sep 24, 2017

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.

@yorickpeterse
Copy link

I think this should be fixed by 8a0138d?

@nagisa nagisa closed this as completed Sep 26, 2020
@YaLTeR
Copy link
Contributor

YaLTeR commented Dec 30, 2020

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, ...).

8a0138d adds a method to get the handle to the calling library itself, which is not really related.

@nagisa nagisa reopened this Dec 30, 2020
@nagisa
Copy link
Owner

nagisa commented Dec 30, 2020

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
Copy link
Owner

nagisa commented Dec 30, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants