We have a .NET library that is referencing one of our unmanaged dlls, lets say:
Thus far, Unmanaged.dll is only 32-bit, so the DotNet.dll is marked with 32-bit CPU type.
64-bit support needs to be added. How to organize the dlls? IL code of DotNet.dll will be the same for both 32-bit and 64-bit versions.
In this case a developer using these libraries is forced to make 2 applications: a 32-bit one and a 64-bit one. But in this case the know exactly what is happening.
This is the same as Option 1 except DotNet.dll has CPU Type of AnyCPU.
I do not like this one because a developer using these libraries, when redistributing their application cannot do a good job of making their application not crash without setting the CPU type on their application:
This makes Option 1 superior to Option 2.
DotNet.dll at runtime would determine what bitness it is being run under, then PInvoke the correct Unmanaged.dll.
I would choose option 3, compile the managed assembly for AnyCPU and name the unmanaged assemblies for their architecture. I see two separate concerns that factor into this decision:
I think .NET developers would not expect to have to reference a separate file for each architecture. I would use AnyCPU in order to have exactly one dll.
If you use AnyCPU for the managed assembly, there is exactly one dll, so this is a moot point.
For the unmanaged assembly, there may be an expectation that files compiled for different architectures are named differently. From a technical standpoint, naming the files differently allows you to put the files for both architectures in the same directory; this means calling into a different file at runtime depending on the architecture, but this is not a huge burden. I would name the files differently.
Option 3 seems like the easiest, while Option 1 seems like the safest. Just from the perspective of which library to call, it doesn't seem like it would be that difficult to manage them unless you're dealing with a huge number of calls. The main issue is that you're going to have to declare any given function twice, using different names for 32- and 64-bit versions, then just change the DllImport
attribute to point to the proper target. Your stub function will have to decide at runtime which one to call.
Note that, logistics aside, there's no need to include both in your library folder. As long as you don't invoke a call to the "wrong" library, excluding it won't have any impact.
What I do is this:
I ship DotNet.dll compiled for AnyCPU with portable P/Invoke directives (like the API declarations have to be).
I ship unmanaged_32.bin and unmanaged_64.bin and install only the correct one for architecture as unmanaged.dll at install time.
A trick that still works would be to install unmanaged.dll like so:
x86: C:\Program Files (x86)\Common Files\unmanaged.dll x64: C:\Program Files\Common Files\unmanaged.dll
If C:\Program Files\Common Files is in the system path, this will cause P/Invoke to grab the correct DLL automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With