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

Feature Request: Load library from embedded resource #5

Open
RoySalisbury opened this issue May 16, 2018 · 10 comments
Open

Feature Request: Load library from embedded resource #5

RoySalisbury opened this issue May 16, 2018 · 10 comments

Comments

@RoySalisbury
Copy link

I've done this in the past so I know its possible (on windows anyway). It would be nice to be able to load the library from an embedded resource so all libraries can be distributed with a single assembly.

Something along the lines of exporting the library to a specific app/version name into a temporary location, and then load the library from there. As part of the app domain unloading you can remove the library (or leave it).

@mellinoe
Copy link
Owner

Hmm, I'm not familiar with how you'd accomplish this. From a cursory search, it doesn't look like there's just a "LoadFromMemory" function -- probably with good reason. Obviously, you could split out the embedded data into a file and then load that, but I'm guessing that's not what you mean.

Is there actually functionality in most OS's that make this possible, portably?

@simplexidev
Copy link

I know that there is a file in Eto.Forms that can accomplish this in some way, but it returns an Assembly instance rather than an IntPtr.

@simplexidev
Copy link

Here's a link to the file: EmbeddedAssemblyLoader.cs

@mellinoe
Copy link
Owner

@tom-corwin That linked code loads a managed assembly that is embedded as a resource. Doing that is pretty straightforward, because there's an explicit API for it (Assembly.Load). I think what @RoySalisbury is asking about is a bit different, though (loading a native dynamic library that has been embedded).

@simplexidev
Copy link

simplexidev commented May 19, 2018

@mellinoe It's still an idea. You might be able to use System.Reflection.Assembly.GetManifestResourceStream(string) to read the native dll from the embedded resx, and write it to an external file before an attempted load, bouncing off of @RoySalisbury

@RoySalisbury
Copy link
Author

Yes, you have to load it from the file system. What I have done in the past was ready the byte[] from an embedded resource, save it to a temp location under as (for example)

MyAssemblyName.v1.0.0.2.[UniqueGuid].NativeLibraryName.dll

I wanted it unique so that it would not clash with other instances of the same app. Then use the standard LoadLibrary/DelegatePointer/FreeLibrary methods using that file. And in the dispose for the app, I would (after I unloaded the library), delete the file to clean up.

Sometimes if the app crashed it would get left behind, and I would usually solve that by using a TEMP directory that usually gets emptied at some point anyway. Or even using a RAM drive that got destroyed every time I rebooted. There are countless ways to handle the saving and cleanup (perhaps your own app cleans it up the next tie it starts .. who knows).

But, it allows for the native library to just be distributed with the managed library. Wont work for EVERY case (perhaps the library needs to be kernel specific for linux), but its going to work for 98% of apps. I have even done it for .EXE's that I needed to shell out to (ffdshow on windows). And I know Microsoft does it for some things as well.

@simplexidev
Copy link

If it's alright with @mellinoe, I'd be happy to try to implement this feature. This would definitely come in handy for various uses.

@mellinoe
Copy link
Owner

mellinoe commented May 19, 2018

Not trying to shut down the discussion or anything, but I think it would be best to implement this outside of the library. You can already load a library from an arbitrary path, so all that you would need to do to accomplish this is:

  • Open a manifest resource stream
  • Dump the stream to a file (somewhere)
  • Pass that file's path to the method that already exists in here

The implementation is not all that interesting (it's just copying bytes around), but it involves making a policy decision about where to put the file, what to name it, how long that file is retained, etc. which I'd rather not be in the business of. If there were some OS-level API that actually let you load a dynamic library from raw bytes, then perhaps it would make more sense to include in this library directly.

@simplexidev
Copy link

Not trying to shut down the discussion or anything, but I think it would be best to implement this outside of the library.
...
If there were some OS-level API that actually let you load a dynamic library from raw bytes, then perhaps it would make more sense to include in this library directly.

That's a fair point, thank you for clarifying the scope of the project. 🙂

@simplexidev
Copy link

simplexidev commented May 21, 2018

@RoySalisbury This PR add an EmbeddedPathHandler class that copies the library to a folder with the executing applications name in the temporary folder determined by the OS environment variables, and loads it from there.

Note that the origional NativeLibraryLoader code is slimmed down, but the logic and member names are the same.

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

3 participants