Introduction
This is maybe a novel solution to the 64 vs 32-bit DLL problem when doing P/Invoke (aka DllImport) in .NET.
Background
When building a .NET assembly for the "AnyCPU
" target, you don't know until run-time if it will be running in a 64-bit or 32-bit process. If the assembly calls on a native DLL that is also distributed with the assembly, then you must install the correct native DLL -- 32-bit or 64-bit. This creates headaches, requiring either multiple install packages or other work to ensure the proper DLL gets installed.
One solution is to target x86 for the .NET assembly and distribute it with a 32-bit native DLL. But that wastes performance on 64-bit machines.
Using the Code
Here's a solution which allows you to distribute a single install package and still get the correct DLL to run with the .NET assembly.
First, there is a .NET interface defined which will permit access to the native DLL functions. For example:
public interface xyz { int Add(int a, int b); }
Now, build two versions of the native DLL with different names, for example, "Native-x86.dll" and "Native-x64.dll".
Next, define two implementations for the interface; one uses DllImport
on the 32-bit DLL and the other one uses the 64-bit DLL.
public xyz_x86 : xyz
{
private const string DLL_Filename = "Native-x86.dll";
[DLLImport(DLL_Filename)] private static extern int NativeAdd(int a, int b);
public int Add(int a, int b) { return NativeAdd(a,b); }
}
Now just make an exact copy of this class and change the DLL_Filename
:
public xyz_x64 : xyz
{
private const string DLL_Filename = "Native-x64.dll";
[DLLImport(DLL_Filename)] private static extern int NativeAdd(int a, int b);
public int Add(int a, int b) { return NativeAdd(a,b); }
}
At runtime, it is now just a matter of choosing the implementation that does not throw an exception:
static void Main()
{
xyz MyAdder = new xyz_x86();
try { int junk = MyAdder.Add(1,2); } catch { MyAdder = new xyz_x64(); }
}
Now, there is only one install package and it installs both x86 and x64 DLLs... one of them won't work but that's okay now.