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

Loading multiple implementation of an interface #92

Open
RagibHasin opened this issue Jul 22, 2022 · 5 comments
Open

Loading multiple implementation of an interface #92

RagibHasin opened this issue Jul 22, 2022 · 5 comments

Comments

@RagibHasin
Copy link

The glossary section in docs.rs index mentions:

user crate:A crate that depends on an interface crate and loads 1 or more implementation crates for it.

But calling RootModule::load_from_file twice with different implementation DLL files returns a reference to the implementation from the first DLL on both occurrences.

Delving into its source code, it seems to keep a single static reference per interface type, which is initialized on the first call to RootModule::load_from_file and all subsequent calls to RootModule::load_from_file returns a copy of it irrespective of the parameter it has been called with.

Now, how multiple implementation DLLs of some interface can be loaded? If it needs some change in the abi_stable crate, I would be happy to help.

@rodrimati1992
Copy link
Owner

Loading multiple implementations of an interface can be done with:

abi_stable::library::lib_header_from_path(&library_path)
    .and_then(|x| x.init_root_module::<RootModule_Ref>())

I'm fine with PRs to ducument that it can be done this way.

@RagibHasin
Copy link
Author

Many thanks, @rodrimati1992, for the prompt help. I would try to send a PR once I've verified it in my codebase.

@RagibHasin
Copy link
Author

Thanks a lot @rodrimati1992. It is working as intended. I am going to send a PR detailing this in docs. Should I add this use case in the big example in README or just mention it in the docs of the abi_stable::library::lib_header_from_path function?

@HeroicKatora
Copy link

There's a conceptual problem, I think: By design a library defines a single entry, which is a function that reveals its root module definition by loading and executing the libraries entry point. Since unloading is out-of-scope (good!) this implies it is not possible to speculatively load a library to discover the right implementation and right dynamic library since that will amass waste.

Is there a plan for discovering available implementations without running into this problem?

Something rather curious I've been pondering is the possibility of exporting symbols by utilizing relocations. It is possible to export a static containing a pointer. You can't compute with said pointer in const, but it can be relocated when used in a static. A proc-macro can produce structs that suitably contain all of the serialized type-descriptions as well as pointer fields with the actual values as relocations. This might alleviate the need for executing code of the implementor, parsing such an struct could then work with a completely separate mechanism that does not rely on actually loading the library itself. One only needs to load for the purpose of having the linker resolve the relocations to their final value and then utilize the function / symbols exported for such module descriptions.

It's a bit of moon shot to completely replace the mechanism for discovering and loading shared libraries but it could be worth it. Loading is not possible if the library is distrusted anyways and it would be nice if the implementations in a binary could be listed regardless.

@lbfalvy
Copy link

lbfalvy commented Feb 25, 2024

@HeroicKatora I'm just about starting out with all this ABI stuff but I have a similar problem. Is it viable to have a worker process (pool?) speculatively load libraries and report back with the data we need to decide which ones should actually be loaded? I would expect that even though the libraries run code, if all we do in them is return a struct and then read some small isolated static data from that struct, most of the data or even code would never be read from disk, so the cost of discovery is just the strictly necessary system calls and some IPC.

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

No branches or pull requests

4 participants