前言
标题不知道怎么确切地命名,在.net的托管世界里,有时不得不使用c的某个动态库,比如ocr、opencv等,如果幸运,有前人已经包装出.net版本,但有些不非常流行的库,只能自己使用pinvoke或c++ cli包装了,比如笔者就遇到了一个,mqtt客户端库。
Pinvoke的多平台问题
如果您没有接触过如何调用非托管dll,没有了解过c#的DllImportAttribute,可以看看以下资料:
1、DllImportAttribute
2、Pinvoke
3、extern 关键字
多平台支持问题来源:
1、c的库是编译时确定了平台,比如x86或x64,一个dll不能在运行时既支持x86也支持x64,所以如果引用它的.net程序还想支持any cpu,只能在运行后根据平台去加载对应平台的c的库;
2、DllImport 特性要求传入string dllName参数,这个参数可以是相对路径或绝对路径,但.Net的特性有个要求:特性实参必须是特性形参类型的常量表达式、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程序也可是any cpu了。