This is a mirror of official site: http://jasper-net.blogspot.com/

Dealing With Native DLLs in .NET “AnyCPU” Builds

| Monday, February 14, 2011
A .NET application can be compiled using the “AnyCPU” configuration, meaning the application runs as 32 bit on a 32 bit OS, and 64 on a 64 bit OS. As long as the application is purely managed, everything should be just fine.

However, if the application must use some native DLL through interop (e.g. P/Invoke), then “AnyCPU” may be an issue. A native DLL cannot be both 32 and 64 bit – it’s one or the other.

The traditional solution to the problem is to switch the .NET build to a “Win32” or “x64” configuration, thus aligning it with the “bitness” of the native DLL. But suppose I have two versions of the native DLL, can I use the correct one when doing interop so that “AnyCPU” just works as expected?

The answer is yes. Here’s one relatively convenient way to do it. Suppose I want to P/invoke to a function named foo() in some DLL with both 32 and 64 bit versions (named e.g. mynative32.Dll and mynative64.dll). Here’s some code that can make the interop seamless:

[DllImport("mynative32.dll", EntryPoint = "foo")]
private extern static void foo32();

[DllImport("mynative64.dll", EntryPoint = "foo")]
private extern static void foo64();

public static void foo() {
  if(Environment.Is64BitProcess)
     foo64();
  else
     foo32();
}

The actual inetrop methods are separated, accessing the proper DLL and name corrected using the EntryPoint property. Note they are marked private, so they are not callable directly.

The “actual” method checks the Environment.Is64BitProcess property, indicating whether we’re running in a 64 bit process or not, allowing the correct function to be invoked. The caller does not know (nor cares) that this is actually happening behind the scenes.

Interestingly enough, the Environment.Is64BitProcess property was introduced in .NET 4. If you’re running in a prior .NET version, the check is a bit more complex and might look something like this:

public static class ProcessHelper {
  [StructLayout(LayoutKind.Sequential)]
  internal struct SYSTEM_INFO {
     public ushort processorArchitecture;
     ushort reserved;
     public uint pageSize;
     public IntPtr minimumApplicationAddress;
     public IntPtr maximumApplicationAddress;
     public IntPtr activeProcessorMask;
     public uint numberOfProcessors;
     public uint processorType;
     public uint allocationGranularity;
     public ushort processorLevel;
     public ushort processorRevision;
  }

  [DllImport("kernel32.dll")]
  internal static extern void GetNativeSystemInfo(ref SYSTEM_INFO si);

  [DllImport("kernel32.dll")]
  internal static extern bool IsWow64Process(IntPtr handle, out bool result);

  [DllImport("kernel32.dll")]
  internal static extern IntPtr GetCurrentProcess();

  public static bool Is64BitProcess {
     get {
        SYSTEM_INFO si = new SYSTEM_INFO();
        GetNativeSystemInfo(ref si);
        if(si.processorArchitecture == 0)   // zero meaning x86 (check the docs)
           return false;


Read more: Pavel's Blog

Posted via email from Jasper-net

0 comments: