Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
371 views
in Technique[技术] by (71.8m points)

.net - CPU Architecture Independent P/Invoke: Can the DllName or path be "dynamic"?

Is there a way to have the particular DLL referenced by a P/Invoke (DllImport) signature depend on the CPU architecture?

I'm working on an application that loads a large number of method signatures from a native dll from a third party vendor, in this case the user-space interface DLL to a piece of hardware. That vendor has now started supplying both x86 and x64 versions of the DLL now, and I think my app would benefit from running as a 64bit process. Except for this one DLL, everything is .NET code, so building as "Any CPU" would work.

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

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

NB: Because it is essential that the version of this user-space DLL match the installed kernel driver for the hardware, the DLL is not bundled with our app, but instead we depend on the vendor installer to place it in a directory in the %PATH%.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

Maybe this would 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 the native library with its full path before P/Invoke itself tries to load it.

What do you think?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...