日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DllImport 自动选择x64或x86 dll

發布時間:2023/12/4 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DllImport 自动选择x64或x86 dll 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

標題不知道怎么確切地命名,在.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的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。