前言

标题不知道怎么确切地命名,在.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了。

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")]
static extern int MethodC ( );

实验结果

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

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

实验总结

可以一如既往的使用DllImport特性,如果想要any 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 handle,            ref MQTTAsync_connectOptions options);[DllImport("kernel32")]            private static extern IntPtr LoadLibraryA([MarshalAs(UnmanagedType.LPStr)] string fileName);             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);}
}

笔者最近在搞mqtt,使用pinvoke将c版本的mqtt客户端包装,项目开源在github上,如果你感兴趣,可以过来看看

https://github.com/xljiulang/Paho.MqttDotnet

原文地址:http://www.cnblogs.com/kewei/p/7011387.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

DllImport 自动选择x64或x86 dll相关推荐

  1. SVM原理详细图文教程来了!一行代码自动选择核函数,还有模型实用工具

    公众号关注 "视学算法" 设为 "星标",DLCV消息即可送达! 贾浩楠 发自 凹非寺 转自 | 量子位 SVM?老分类算法了,轻松拿下. 然而,每一次老板让你 ...

  2. js鼠标略过自动选择当前行

    js鼠标略过自动选择当前行 效果图: 相关代码: <!DOCTYPE html> <html><head><meta charset="utf-8& ...

  3. SVM原理详细图文教程来了!一行代码自动选择核函数

    点击上方,选择星标或置顶,不定期资源大放送! 阅读大概需要5分钟 Follow小博主,每天更新前沿干货 转载自:量子位 SVM?老分类算法了,轻松拿下. 然而,每一次老板让你讲解SVM,或每一次面试被 ...

  4. centos让yum自动选择最快的源

    由于yum中有的mirror速度是非常慢的,如果yum选择了这个mirror,这个时候yum就会非常慢,对此,可以下载fastestmirror插件,它会自动选择最快的mirror: yum inst ...

  5. ECshop网点程序优化-后台添加类目自动选择上次父类目并计算Sort Order

    如果在ECshop后台批量添加过大量类目的人都能体会到是多么的不方便(这点还是要说一下ECshop的产品经理,细节上还是要多注意),每次添加都需要在几百个类目里面找到要添加的父类目也是一个麻烦事,比如 ...

  6. matlab 线性拟合相关系数,Matlab自动选择相关性最高波段并拟合曲线

    前言 之前完成老师任务的时候写的,里面有一个错误,就是误差分析的时候有个公式错了,自己注意下. 代码 %作者:山科_xxin %时间:2016.10 clear;clc; [NUM]=xlsread( ...

  7. 下拉框根据输入文字自动选择和输入提示

    要求 根据输入商品名字.对应的下拉框自动选择到对应名字的商品.. 实现方法. 1.为每个option设置一个属性.用来对应文本框中输入的拼音,或者其他简码. 此方法缺点..有限制性.属性局限了文本框中 ...

  8. 解决:IE中不能自动选择UTF-8编码的解决方法

    解决:IE中不能自动选择UTF-8编码的解决方法 参考文章: (1)解决:IE中不能自动选择UTF-8编码的解决方法 (2)https://www.cnblogs.com/chenshuo/p/443 ...

  9. 自动选择SVG和VML的WEB页面

    2019独角兽企业重金招聘Python工程师标准>>> 自动选择SVG和VML的WEB页面 问题 在WEB上使用二维图形编程的人员现在面临者一个两难的选择,是使用SVG,还是VML? ...

最新文章

  1. 【2017-05-30】WebForm文件上传。从服务端删除文件
  2. html坐标定位图解,HTML5地理定位实例
  3. sql添加,修改数据及删除表,表约束、字段及数据
  4. AMD院士站台 异构计算与OpenCL编程师资培训首站清华开讲
  5. perl里面隐式的继承
  6. [转载]JavaScript 的轻框架开发
  7. 10kv配电网潮流 matlab,关于用matlab计算配电网三相潮流计算,请大家帮忙检验下!...
  8. 使用Scrapy框架编写爬虫
  9. python timer模块_Python timeit模块的使用实践
  10. jasperreport linux 中文不能显示的解决方法
  11. notepad++设置自动刷新文本(中文版/英文版)
  12. 续:Fucking 这个网站!
  13. 《编码规范和测试方法——C/C++版》学习笔记 ·002
  14. 用python画玫瑰花-用python画一朵玫瑰给你
  15. CarMaker中关于交通目标行人横穿的问题
  16. GNS3交换机如何划分vlan
  17. GPS模拟器算法(C#)
  18. e盘根目录出现个Msdia80.dll怎么办?
  19. eslint 修改standard规则
  20. github php right way,GitHub - seraph526/php-the-right-way: 收集PHP最佳实践、编码规范和权威学习指南,方便PHP开发者阅读和查找...

热门文章

  1. 异常检测之浅谈入侵检测
  2. 【项目 报错】 项目启动,内存溢出 可能出现的各种报错
  3. webform 页面传值的方法总结
  4. Oracle CRS stack is already configured and will be running under init(1M)
  5. Avalonia跨平台入门第二十二篇之人脸检测
  6. 从 ThreadLocal 到 AsyncLocal
  7. NET问答: 为什么 String.IndexOf 在 .net5 和 netcore3 中返回值不一样?
  8. 【EFCORE笔记】异步查询工作原理注释标记
  9. 应用程序自动更新组件GeneralUpdate3.2.1发布
  10. 如何在 ASP.NET Core 中使用 LazyCache