c#的dllimport使用方法詳解

DllImport是System.Runtime.InteropServices命名空間下的一個屬性類毙沾,其功能是提供從非托管DLL導出的函數(shù)的必要調用信息

DllImport是System.Runtime.InteropServices命名空間下的一個屬性類骗卜,其功能是提供從非托管DLL導出的函數(shù)的必要調用信息

DllImport屬性應用于方法,要求最少要提供包含入口點的dll的名稱。
DllImport的定義如下:

復制代碼 代碼如下:

[AttributeUsage(AttributeTargets.Method)]
public class DllImportAttribute: System.Attribute
{
public DllImportAttribute(string dllName) {…} //定位參數(shù)為dllName
public CallingConvention CallingConvention; //入口點調用約定
public CharSet CharSet;?????????????????????????????????? //入口點采用的字符接
public string EntryPoint;? //入口點名稱
public bool ExactSpelling;?? //是否必須與指示的入口點拼寫完全一致寇仓,默認false
public bool PreserveSig;? //方法的簽名是被保留還是被轉換
public bool SetLastError;? //FindLastError方法的返回值保存在這里
public string Value { get {…} }
}

用法示例:

復制代碼 代碼如下:

[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);

以上是用來寫入ini文件的一個win32api举户。????????? 用此方式調用Win32API的數(shù)據(jù)類型對應:DWORD=int或uint,BOOL=bool焚刺,預定義常量=enum敛摘,結構=struct。?

DllImport會按照順序自動去尋找的地方: 1乳愉、exe所在目錄 2兄淫、System32目錄 3、環(huán)境變量目錄所以只需要你把引用的DLL 拷貝到這三個目錄下 就可以不用寫路徑了 或者可以這樣server.MapPath(.\bin\*.dll)web中的蔓姚,同時也是應用程序中的 后來發(fā)現(xiàn)用[DllImport(@"C:\OJ\Bin\Judge.dll")]這樣指定DLL的絕對路徑就可以正常裝載捕虽。 這個問題最常出現(xiàn)在使用第三方非托管DLL組件的時候,我的也同樣是這時出的問題,Asp.Net Team的官方解決方案如下: 首先需要確認你引用了哪些組件,那些是托管的,哪些是非托管的.托管的很好辦,直接被使用的需要引用,間接使用的需要拷貝到bin目錄下.非托管的處理會比較麻煩.實際上,你拷貝到bin沒有任何幫助,因為CLR會把文件拷貝到一個臨時目錄下,然后在那運行web,而CLR只會拷貝托管文件,這就是為什么我們明明把非托管的dll放在了bin下卻依然提示不能加載模塊了.  具體做法如下:  首先我們在服務器上隨便找個地方新建一個目錄,假如為C:\DLL  然后,在環(huán)境變量中,給Path變量添加這個目錄  最后,把所有的非托管文件都拷貝到C:\DLL中.  或者更干脆的把DLL放到system32目錄  對于可以自己部署的應用程序坡脐,這樣未償不是一個解決辦法泄私,然而,如果我們用的是虛擬空間备闲,我們是沒辦法把注冊PATH變量或者把我們自己的DLL拷到system32目錄的晌端。同時我們也不一定知道我們的Dll的物理路徑√裆埃  DllImport里面只能用字符串常量咧纠,而不能夠用Server.MapPath(@"~/Bin/Judge.dll")來確定物理路徑。ASP.NET中要使用DllImport的泻骤,必須在先“using System.Runtime.InteropServices;”不過漆羔,我發(fā)現(xiàn),調用這種"非托管Dll”相當?shù)穆啵赡苁且驗槲业姆椒ㄐ枰h程驗證吧演痒,但是實在是太慢了。經過一翻研究趋惨,終于想到了一個完美的解決辦法首先我們用

復制代碼 代碼如下:

[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path);

[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);

[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);

分別取得了LoadLibrary和GetProcAddress函數(shù)的地址鸟顺,再通過這兩個函數(shù)來取得我們的DLL里面的函數(shù)。
我們可以先用Server.MapPath(@"~/Bin/Judge.dll")來取得我們的DLL的物理路徑希柿,然后再用LoadLibrary進行載入诊沪,最后用GetProcAddress取得要用的函數(shù)地址

以下自定義類的代碼完成LoadLibrary的裝載和函數(shù)調用

復制代碼 代碼如下:

public class DllInvoke
??? {???????????
??????? [DllImport("kernel32.dll")]
??????? private extern static IntPtr LoadLibrary(String path);

??????? [DllImport("kernel32.dll")]??
??????? private extern static IntPtr GetProcAddress(IntPtr lib, String funcName);

??????? [DllImport("kernel32.dll")]????
??????? private extern static bool FreeLibrary(IntPtr lib);????

??????? private IntPtr hLib;??

??????? public DllInvoke(String DLLPath)??
??????? {??????????
??????????? hLib = LoadLibrary(DLLPath);?
??????? }??????

??????? ~DllInvoke()????
??????? {???????
??????????? FreeLibrary(hLib);?
??????? }???????

??????? //將要執(zhí)行的函數(shù)轉換為委托?
??????? public Delegate Invoke(String APIName,Type t)????
??????? {??????????
??????????? IntPtr api = GetProcAddress(hLib, APIName);??
??????????? return (Delegate)Marshal.GetDelegateForFunctionPointer(api,t);????
??????? }
??? }

下面代碼進行調用

復制代碼 代碼如下:

public delegate int Compile(String command, StringBuilder inf);
??????????? //編譯
??????????? DllInvoke dll = new DllInvoke(Server.MapPath(@"~/Bin/Judge.dll"));
??????????? Compile compile = (Compile)dll.Invoke("Compile", typeof(Compile));
??????????? StringBuilder inf;
??????????? compile(@“gcc a.c -o a.exe“,inf);//這里就是調用我的DLL里定義的Compile函數(shù)

大家在實際工作學習C#的時候,可能會問:為什么我們要為一些已經存在的功能(比如Windows中的一些功能曾撤,C++中已經編寫好的一些方法)要重新編寫代碼端姚,C#有沒有方法可以直接都用這些原本已經存在的功能呢?答案是肯定的挤悉,大家可以通過C#中的DllImport直接調用這些功能渐裸。???
DllImport所在的名字空間 using System.Runtime.InteropServices;???
MSDN中對DllImportAttribute的解釋是這樣的:可將該屬性應用于方法巫湘。DllImportAttribute 屬性提供對從非托管 DLL
導出的函數(shù)進行調用所必需的信息。作為最低要求昏鹃,必須提供包含入口點的 DLL 的名稱尚氛。??? DllImport 屬性定義如下:

復制代碼 代碼如下:

namespace System.Runtime.InteropServices??
?{??  
???? [AttributeUsage(AttributeTargets.Method)]??
???? public class DllImportAttribute: System.Attribute?
???? {??  
???????? public DllImportAttribute(string dllName)
???????? {...}??    

???????? public CallingConvention CallingConvention;??
???????? public CharSet CharSet;??  
???????? public string EntryPoint;??  
???????? public bool ExactSpelling;??  
???????? public bool PreserveSig;??    
???????? public bool SetLastError;??  
???????? public string Value { get {...} }??  
???? }??
?}

說明:????
1、DllImport只能放置在方法聲明上洞渤。
2阅嘶、DllImport具有單個定位參數(shù):指定包含被導入方法的 dll 名稱的
dllName 參數(shù)。????
3载迄、DllImport具有五個命名參數(shù):?
a讯柔、CallingConvention
參數(shù)指示入口點的調用約定。如果未指定 CallingConvention护昧,則使用默認值
CallingConvention.Winapi魂迄。
b、CharSet 參數(shù)指示用在入口點中的字符集惋耙。如果未指定 CharSet捣炬,則使用默認值
CharSet.Auto。????   
c绽榛、EntryPoint 參數(shù)給出 dll 中入口點的名稱湿酸。如果未指定
EntryPoint,則使用方法本身的名稱灭美。?????    
d稿械、ExactSpelling 參數(shù)指示 EntryPoint
是否必須與指示的入口點的拼寫完全匹配。如果未指定 ExactSpelling冲粤,則使用默認值 false。?????    
e页眯、PreserveSig
參數(shù)指示方法的簽名應當被保留還是被轉換梯捕。當簽名被轉換時,它被轉換為一個具有 HRESULT返回值和該返回值的一個名為 retval
的附加輸出參數(shù)的簽名窝撵。如果未指定 PreserveSig傀顾,則使用默認值 true。?????    
f碌奉、SetLastError 參數(shù)指示方法是否保留
Win32"上一錯誤"短曾。如果未指定 SetLastError,則使用默認值 false赐劣。?????  
4嫉拐、它是一次性屬性類。?????
  
5魁兼、此外婉徘,用 DllImport 屬性修飾的方法必須具有 extern 修飾符。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盖呼,隨后出現(xiàn)的幾起案子儒鹿,更是在濱河造成了極大的恐慌,老刑警劉巖几晤,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件约炎,死亡現(xiàn)場離奇詭異,居然都是意外死亡蟹瘾,警方通過查閱死者的電腦和手機圾浅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來热芹,“玉大人贱傀,你說我怎么就攤上這事∫僚В” “怎么了府寒?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長报腔。 經常有香客問我株搔,道長,這世上最難降的妖魔是什么纯蛾? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任纤房,我火速辦了婚禮,結果婚禮上翻诉,老公的妹妹穿的比我還像新娘炮姨。我一直安慰自己,他們只是感情好碰煌,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布舒岸。 她就那樣靜靜地躺著,像睡著了一般芦圾。 火紅的嫁衣襯著肌膚如雪蛾派。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天个少,我揣著相機與錄音洪乍,去河邊找鬼。 笑死夜焦,一個胖子當著我的面吹牛壳澳,可吹牛的內容都是我干的。 我是一名探鬼主播糊探,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼钾埂,長吁一口氣:“原來是場噩夢啊……” “哼河闰!你這毒婦竟也來了?” 一聲冷哼從身側響起褥紫,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤姜性,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后髓考,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體部念,經...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年氨菇,在試婚紗的時候發(fā)現(xiàn)自己被綠了儡炼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡查蓉,死狀恐怖乌询,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情豌研,我是刑警寧澤妹田,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站鹃共,受9級特大地震影響鬼佣,放射性物質發(fā)生泄漏。R本人自食惡果不足惜霜浴,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一晶衷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阴孟,春花似錦晌纫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至类溢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間露懒,已是汗流浹背闯冷。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留懈词,地道東北人蛇耀。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像坎弯,于是被迫代替她去往敵國和親纺涤。 傳聞我的和親對象是個殘疾皇子译暂,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內容