Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

.NET Interop with 32 and 64-bit DLLs

4.28/5 (16 votes)
11 Dec 2014CPOL1 min read 59.8K  
A novel solution to the 32 vs 64-bit DLL interop problem

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:

C#
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.

C#
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:

C#
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:

C#
static void Main()
{
    xyz MyAdder = new xyz_x86();
    try { int junk = MyAdder.Add(1,2); } catch { MyAdder = new xyz_x64(); }
    // Now MyAdder is connected to a working DLL!
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)