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