-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
DllImport cross-platform best practices? #8295
Comments
@hintdesk I just saw your issue and wanted to throw in my two cents. For your first question, as far as I know this won't work under CoreCLR. The As for your second question, this will definitely work. This is the correct and preferred way to do this sort of dynamic library lookup, IMHO. The way I'd recommend doing it is to place the path/name of the DLL in a Hope this helps! |
@wjk The problem with this approach is that this is really bad experience for us. Windows, Linux, Mac, Pi And we use a native library that needs to be shipped for each of those.
That makes things like distributing nuget packages very awkward. It would be much nicer if we could have something like Mono |
I am new to .NET and the first thing I tried was to check its performance as I often need to squeeze out everything I can from the code. So I tried P/Invoke and it was a touch faster than JNI. It would be absolutely amazing had it been possible to use P/Invoke in multi-platform .NET Core applications and libraries. Ideally it would have the same compiled C# code for all platforms and multiple platform-specific shared libraries. So far it seems that is not possible. |
This issue with DllImport completely breaks the entire "single assembly" concept, and truly makes any type of cross-platform assembly that relies on an unmanaged library either impossible or too cumbersome to upkeep. As far as I have discovered, I have a very limited set of options, each of which is terrible, especially when dealing with an assembly to support both 32 and 64 bit unmanaged libraries.
The perfect solution would be to simply be able to use a non-constant name for DllImport, though I understand that restriction is not specific to DllImport, but a restriction of Attributes in general. Another solution, one that I have kicked around implementing myself is to create a "DllImport" type of function that also uses the appropriate underlying platform "LoadLibrary", and using reflection to generate methods from the function pointers, but this seems inelegant and clumsy, as well as prone to problems. I understand the many naming conventions and file extensions of different platforms is a serious issue, but with would it not be possible for dare I even say an elaborate regular expression as a last ditch effort to find a missing lib, or even simpler (maybe) yet, a way to use a "resolve" event that gets raised when a native lib cannot be found (just like the AssemblyResolve event works for managed libraries). This would allow the end user to implement their own logic and search patterns to find the file, but not enforce any type of behavior. |
@ForeverZer0 Have you looked into The only "gotcha" I can see is that you must load the assembly that contains the P/Invoke in question using Hope this helps! |
@wjk Is there a way to do this on the default context? |
@ayende I don't think so, unfortunately. The best I can think of is to have the entry point DLL do nothing but create an assembly load context and then use reflection to load the real entry point using that context. As lame as it sounds, as far as I know it's the only way to apply a custom assembly load context to the entire system. As I understand it all assemblies (directly or indirectly, explicitly through reflection or implicitly via compile-time references) loaded by an assembly in a certain load context will inherit that load context. |
@wjk Looking into your suggestions now, and it does seem plausible to implement. I am making a rather large wrapper, with hundreds of external functions. The library has different builds for each platform and processor architecture, with platform specific naming conventions for each. So using the above method, creating my own LoadContext subclass, I could use a single name for the "DllImport", and when use the overridden "LoadUnmanagedDLL" to return the proper handle after determining the platform, CPU, etc, etc? If so, I suppose I have a few questions.
|
@ForeverZer0 The best way to handle this in .NET Core is put the native libraries into platform specific folders in the NuGet package for you library and the rest will happen automatically. And you can just keep using regular DllImport. There are number of packages that do this today. For example, Mono Game for .NET Core does this: MonoGame/MonoGame#5339 (comment) |
Closing out question. Though please let us know if you still have a question around this topic. |
Hi,
I would like to connect to my Canon DSLR camera on Windows and Mac over Canon EDSDK. In Windows, I can use DllImport to call C++ function of the .dll files but I don't know how to use DllImport in Mac.
I would like to ask 2 questions.
Question 1. With Mono, I can do call external framework in Mac like
[DllImport("@executable_path/../Frameworks/EDSDK.framework/EDSDK")]
How can I do the same thing with .NET core? Is there "@executable_path" in .NET Core.
Question 2. For example, I have an import
How should I make this import cross-platform? Does .NET Core have macros like this
Thank you.
The text was updated successfully, but these errors were encountered: