DllImport自动选择x64或x86 dll

  段

Pinvoke的多平台问题

如果您没有接触过如何调用非托管dll,没有了解过c#的DllImportAttribute,可以看看以下资料:

1, DllImportAttribute

2, Pinvoke

3,外面的关键字

多平台支持问题

1, c的库是编译时确定了平台,比如x86或x64,一个dll不能在运行时既支持x86也支持x64,所以如果引用它的. net程序还想支持任何cpu,只能在运行后根据平台去加载对应平台的c的库;

2, DllImport特性要求传入string  dllName参数,这个参数可以是相对路径或绝对路径,但。净的特性有个要求:特性实参必须是特性形参类型的常量表达式,typeof表达式或数组创建表达式。也就是说string  dllName这个值必须在写代码的时候(编译时)就是常量的,而不能在运行时传给它;

3, DllImport特性是密封的,我们不能继承它或修改它的什么逻辑,到达运行时得到与平台匹配的string  dllName的值;

,段

Pinvoke的多平台解决方案

1,绕过DllImport

<强> InteropDotNet

这是开源在github上的一个项目,作者使用了LoadLibrary (c.dll) +, GetProcAddress转换为。Net委托的思想来完成,对于c.dll的所有函数的调用上,实际上已经完全脱离了。Net提供的DllImport特性,所以不受到上面问题2与3的约束,使用本项目,调用c.dll的。Net程序也可是任何cpu了。

,

2笔者的方案

笔者的方案还是沿用。Net的DllImport特性,我们知道DllImport会帮我们自动查找到加载c.dll,然后大概才把DllImport声明的外部实现方法与c.dll的函数地址映射上,如果我们在准备调用c。dll的外部方法之前,通过LoadLibrary Api把c.dll加载到。net程序里,DllImport会不会就不再搜索c.dll而是直接使用?

实验开始

将c.dll对应的x86与x64两个版本都放在。net程序的子目录,构造如下:

dotnet。exe

x86 \ c。dll

x64 \ c。dll

,

dotnet。exe DllImport声明如下:

[DllImport (“c.dll”)]
静态extern int MethodC ();

,

如果默认运行,一定会报找不到dll文件的异常,因为DllImport的本程序目录或系统目录或路径环境下都没有找到c。dll;

如果我们在调用MethodC之前,检测当前进程是32位还是64位,使用windows api的LoadLibrary函数将x86 \ c.dll或x64 \ c。dll加载到本进程,就不会报找不到文件的异常,而且调用MethodC也是正常的。

,

实验总结

可以一如既往的使用DllImport特性,如果想要任何cpu的效果,在调用外部实现方法之前,先将它的dll手动加载。

以下是我的实现代码,在静态构造器里加载正确的dll就行,支持自动x86或x64,而且在asp.net里也能正确找到非托管的dll

<>之前,,,,static  class  MQTTAsync   ,,,{,,,,,,,private  const  string  mqtt3a_dll =,“paho-mqtt3a.dll”;      ,,,,,,,(DllImport (mqtt3a_dll, CallingConvention =, CallingConvention.Cdecl)),,,,,,,, public  static  extern  MqttError  MQTTAsync_connect (   ,,,,,,,,,,,IntPtr 处理,,,,,,,,,,,,,ref  MQTTAsync_connectOptions 选项);   ,,,,,,      ,,,,,,,(DllImport (“kernel32”)],,,,,,,, private  static  extern  IntPtr  LoadLibraryA (   ,,,,,,,,,,(MarshalAs (UnmanagedType.LPStr)], string 文件名),,,,,,,,,static  MQTTAsync ()   ,,,,,,,{,,,,,,,,,,,var  dllFile =, Path.Combine (Environment.Is64BitProcess  ?,“x64”,:,“x86, mqtt3a_dll),,,,,,,,,,,,, if  (HttpContext.Current  !=, null)   ,,,,,,,,,,,{   ,,,,,,,,,,,,,,,dllFile =, Path.Combine (“~ \ \ bin, dllFile);   ,,,,,,,,,,,,,,,dllFile =, HttpContext.Current.Server.MapPath (dllFile);   ,,,,,,,,,,,}   ,,,,,,,,,,,MQTTAsync.LoadLibraryA (dllFile);   ,,,,,,,}   }


DllImport自动选择x64或x86 dll