Processor Architecture Independent P / Invoke: Can a DllName or Path be "Dynamic"?

Is there a way that the specific DLL referenced by the P / Invoke (DllImport) signature depends on the CPU architecture?

I am working on an application that downloads a large number of method signatures from a native dll from a third-party provider, in this case the user-space interface DLL to the piece of hardware. This provider has now begun shipping both the x86 and x64 versions of the DLL now, and I think my application will benefit from running as a 64-bit process. With the exception of this DLL, this is all .NET code, so working on "Any CPU" will work.

All method signatures in the native DLL are the same on the 64-bit one, however the DLL name is different (Foo.dll vs. Foo_x64.dll). Is there any way through the P / Invoke or app.config signatures, I can get it to choose which DLL to load based on the current processor architecture?

If instead of different DLL names it was the same name in different folders, does it open any other parameters?

Note. Since it is important that the version of this DLL for the user matches the installed kernel driver for the hardware, the DLL does not come with our application, but instead we depend on the provider installer to put it in the% PATH% directory.

+10
32bit-64bit pinvoke dllimport
Oct. 15 '09 at 17:01
source share
3 answers

"If instead of different DLL names it was the same name in different folders, does it open any other parameters?"

Maybe this will work for you:

public static class NativeMethods { // here we just use "Foo" and at runtime we load "Foo.dll" dynamically // from any path on disk depending on the logic you want to implement [DllImport("Foo", EntryPoint = "bar")] private void bar(); [DllImport("kernel32")] private unsafe static extern void* LoadLibrary(string dllname); [DllImport("kernel32")] private unsafe static extern void FreeLibrary(void* handle); private sealed unsafe class LibraryUnloader { internal LibraryUnloader(void* handle) { this.handle = handle; } ~LibraryUnloader() { if (handle != null) FreeLibrary(handle); } private void* handle; } // LibraryUnloader private static readonly LibraryUnloader unloader; static NativeMethods() { string path; if (IntPtr.Size == 4) path = "path/to/the/32/bit/Foo.dll"; else path = "path/to/the/64/bit/Foo.dll"; unsafe { void* handle = LoadLibrary(path); if (handle == null) throw new DllNotFoundException("unable to find the native Foo library: " + path); unloader = new LibraryUnloader(handle); } } } 

It consists in explicitly loading your own library with its full path before P / Invoke itself tries to load it.

What do you think?

+11
Dec 08 '09 at 13:46
source share

It is not possible to have one PInvoke signature and get the right behavior. The attribute is burned into metadata and must have constant values. One hack you could do is to have several methods.

 public static class NativeMethods32 { [DllImport("Foo.dll")] public static extern int SomeMethod(); } public static class NativeMethods64 { [DllImport("Foo_x864.dll")] public static extern int SomeMethod(); } public static class NativeMethods { public static bool Is32Bit { return 4 == IntPtr.Size; } public static SomeMethod() { return Is32Bit ? NativeMethods32.SomeMethod(); NativeMethods64.SomeMethod(); } } 

However, this is not the preferred approach. A simpler approach is to make the DLL the same name on multiple platforms and create a PInvoke signature for the platform. This is the approach used by most / all Windows libraries.

+4
Oct 15 '09 at 17:13
source share

I developed a special library for the purpose: InteropDotNet . It introduces a new RuntimeDllImport attribute with resolution of the dynamic library path ("on the fly"). By default you can write

 [RuntimeDllImport("NativeLib", CallingConvention = CallingConvention.Cdecl, EntryPoint = "sum")] int Sum(int a, int b); 

And the library will be solved, depending on the environment. For example, the paths for Win / Linux, x86 / x64:

 x86/NativeLib.dll x86/libNativeLib.so x64/NativeLib.dll x64/libNativeLib.so 
+1
Jul 24 '14 at 12:39 on
source share



All Articles