您好,登錄后才能下訂單哦!
net平臺上,調用dll文件有2種含義
1、調用托管dll,即你使用。net平臺開發的dll,屬于托管代碼
2、調用非托管dll,即傳統的dll,一般是C++,VB,DELPHI等等開發出來的,屬于非托管代碼。
從你的意思中看出來你現在是調用托管的dll,方法是 “在解決方案管理器” - “解決方案”(或項目) 中的任意地方, 右鍵“添加引用”,“瀏覽”,選擇你需要調用的dll文件,確定即可,該dll會自動復制到bin目錄,打包時也會自動復制到你發布的地方。
添加完了引用,現在如何調用呢?
如果有命名空間則引入命名空間,比如你的y。dll里面,是a命名空間,有一個b類,然后有一個無參數靜態方法c
那么調用方法就是a.b.c(),跟你普通的使用類是一樣的
然后是非托管dll
需要添加dll的名稱,以及方法,也就是你所用到的dll的每個方法都需要添加一次,
[DllImport("msvcrt.dll")]
public static extern int puts(string c);
*******************************************************************************************
在最近的項目中,牽涉到項目源代碼保密問題,由于代碼是C#寫的,容易被反編譯,因此決定抽取核心算法部分使用C++編寫,C++到目前為止好像還不能被很好的反編譯,當然如果你是反匯編高手的話,也許還是有可能反編譯。這樣一來,就涉及C#托管代碼與C++非托管代碼互相調用,于是調查了一些資料,順便與大家分享一下:源代碼下載
一. C# 中靜態調用C++動態鏈接
1. 建立VC工程CppDemo,建立的時候選擇Win32 Console(dll),選擇Dll。
2. 在DllDemo.cpp文件中添加這些代碼。
Code
extern"C" __declspec(dllexport) int Add(int a,int b)
{
return a+b;
}
3. 編譯工程。
4. 建立新的C#工程,選擇Console應用程序,建立測試程序InteropDemo
5. 在Program.cs中添加引用:using System.Runtime.InteropServices;
6. 在pulic class Program添加如下代碼:
好了,現在您可以測試Add程序了,是不是可以在C# 中調用C++動態鏈接了,當然這是靜態調用,需要將CppDemo編譯生成的Dll放在DllDemo程序的Bin目錄下
二. C# 中動態調用C++動態鏈接
在第一節中,講了靜態調用C++動態鏈接,由于Dll路徑的限制,使用的不是很方便,C#中我們經常通過配置動態的調用托管Dll,例如常用的一些設計模式:Abstract Factory, Provider, Strategy模式等等,那么是不是也可以這樣動態調用C++動態鏈接呢?只要您還記得在C++中,通過LoadLibrary, GetProcess, FreeLibrary這幾個函數是可以動態調用動態鏈接的(它們包含在kernel32.dll中),那么問題迎刃而解了,下面我們一步一步實驗
1. 將kernel32中的幾個方法封裝成本地調用類NativeMethod
2. 使用NativeMethod類動態讀取C++Dll,獲得函數指針,并且將指針封裝成C#中的委托。原因很簡單,C#中已經不能使用指針了,如下
int hModule = NativeMethod.LoadLibrary(@"c:"CppDemo.dll");
IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "Add");
詳細請參見代碼
*****************************************************************************************
分別介紹 DllImportAttribute屬性、extern關鍵字 、IntPtr類型 這三個方面,向大家介紹如何應用C#調用非托管DLL函數。
C# 如何使用 DllImport Attribute(屬性) 標識 DLL 和函數
System.Runtime.InteropServices.DllImportAttribute
從托管代碼中訪問非托管 DLL 函數之前,需要知道該函數的名稱以及該 DLL 的名稱,然后為 DLL 的非托管函數 編寫 托管定義。
它將用到 static 和 extern 修飾符,此類型的公共靜態成員對于多線程操作是安全的。
DllImport 屬性提供非托管 DLL 函數的調用信息。
示例1 簡單DllImportAttribute 應用
示例2 如何將 DllImportAttribute 應用于方法。
參數說明:
EntryPoint 指定要調用的 DLL 入口點。
SetLastError 判斷在執行該方法時是否出錯(使用 Marshal.GetLastWin32Error API 函數來確定)。
C#中默認值為 false。
CharSet 控制名稱及函數中字符串參數的編碼方式。默認值為 CharSet.Ansi。
ExactSpelling 是否修改入口點以對應不同的字符編碼方式。
CallingConvention 指定用于傳遞方法參數的調用約定。默認值為 WinAPI。
該值對應于基于32位Intel平臺的 __stdcall。
BestFitMapping 是否啟用最佳映射功能,默認為 true。
最佳映射功能提供在沒有匹配項時,自動提供匹配的字符。
無法映射的字符通常轉換為默認的“?”。
PreserveSig 托管方法簽名是否轉換成返回 HRESULT,默認值為 true(不應轉換簽名)。
并且返回值有一個附加的 [out, retval] 參數的非托管簽名。
ThrowOnUnmappableChar 控制對轉換為 ANSI '?' 字符的不可映射的 Unicode 字符引發異常。
C# 關鍵字 extern 的使用
public static extern int MyMethod(int x);
外部修飾符 extern 用于指示外部實現方法,常與 DllImport 屬性一起使用(DllImport 屬性提供非托管 DLL 函數的調用信息)。
若將 abstract 和 extern 修飾符一起使用來修改同一成員是錯誤的。extern 將方法在 C# 代碼的外部實現,而 abstract 意味著在此類中未提供此方法的實現。
因為外部方法聲明不提供具體實現,所以沒有方法體;
此方法聲明只是以一個分號結束,并且在簽名后沒有大括號{ }。
示例3 接收用戶輸入的字符串并顯示在消息框中
程序從 User32.dll 庫導入的 MessageBox 方法。
運行結果: 輸入"Hello"文本后,屏幕上將彈出一個包含該文本的消息框。
Enter your message: Hello
示例4 調用DLL進行計算
該示例使用兩個文件 CM.cs 和 Cmdll.c 來說明 extern。
C 文件是從 C# 程序中調用的外部 DLL。
使用 Visual C++ 命令行將 Cmdll.c 編譯為 DLL:
cl /LD /MD Cmdll.c
文件:Cmdll.c
使用命令行編譯 CM.cs:
csc CM.cs
這將創建可執行文件 CM.exe。
文件:CM.cs
運行此程序,MyMethod 將值 5 傳遞到 DLL 文件,該文件將此值乘以 10 返回。
運行結果:MyMethod() returns 50.
IntPtr 類型的說明
對于平臺調用,應讓參數為 IntPtr 類型,而不是 String 類型。使用 System.Runtime.InteropServices.Marshal 類所提供的方法,可將類型手動轉換為字符串并手動將其釋放。
IntPtr 類型被設計成整數,其大小適用于特定平臺。
在 32 位硬件和操作系統中將是 32 位;
在 64 位硬件和操作系統中將是 64 位。
IntPtr 類型由支持指針的語言使用,并作為在支持與不支持指針的語言間引用數據的一種通用方式。它也可用于保持句柄。例如,IntPtr 的實例廣泛地用在 System.IO.FileStream 類中來保持文件句柄。
IntPtr 類型符合 CLS,而 UIntPtr 類型卻不符合。只有 IntPtr 類型可用在公共語言運行庫中。此類型實現 ISerializable 接口。
*****************************************************************************************
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。