程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c#的dllimport應用辦法詳解

c#的dllimport應用辦法詳解

編輯:C#入門知識

c#的dllimport應用辦法詳解。本站提示廣大學習愛好者:(c#的dllimport應用辦法詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是c#的dllimport應用辦法詳解正文


DllImport是System.Runtime.InteropServices定名空間下的一個屬性類,其功效是供給從非托管DLL導出的函數的需要挪用信息

DllImport屬性運用於辦法,請求起碼要供給包括進口點的dll的稱號。
DllImport的界說以下:


[AttributeUsage(AttributeTargets.Method)]
public class DllImportAttribute: System.Attribute
{
public DllImportAttribute(string dllName) {…} //定位參數為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的數據類型對應:DWORD=int或uint,BOOL=bool,預界說常量=enum,構造=struct。 

DllImport會依照次序主動去尋覓的處所: 1、exe地點目次 2、System32目次 3、情況變量目次所以只須要你把援用的DLL 拷貝到這三個目次下 便可以不消寫途徑了 或許可以如許server.MapPath(.\bin\*.dll)web中的,同時也是運用法式中的 後來發明用[DllImport(@"C:\OJ\Bin\Judge.dll")]如許指定DLL的相對途徑便可以正常裝載。 這個成績最常湧現在應用第三方非托管DLL組件的時刻,我的也異樣是這時候出的成績,Asp.Net Team的官方處理計劃以下: 起首須要確認你援用了哪些組件,那些是托管的,哪些長短托管的.托管的很好辦,直接被應用的須要援用,直接應用的須要拷貝到bin目次下.非托管的處置會比擬費事.現實上,你拷貝到bin沒有任何贊助,由於CLR會把文件拷貝到一個暫時目次下,然後在那運轉web,而CLR只會拷貝托管文件,這就是為何我們明明把非托管的dll放在了bin下卻仍然提醒不克不及加載模塊了.  詳細做法以下:  起首我們在辦事器上隨意找個處所新建一個目次,假設為C:\DLL  然後,在情況變量中,給Path變量添加這個目次  最初,把一切的非托管文件都拷貝到C:\DLL中.  或許更爽性的把DLL放到system32目次  關於可以本身安排的運用法式,如許未償不是一個處理方法,但是,假如我們用的是虛擬空間,我們是沒方法把注冊PATH變量或許把我們本身的DLL拷到system32目次的。同時我們也紛歧定曉得我們的Dll的物理途徑。  DllImport外面只能用字符串常量,而不克不及夠用Server.MapPath(@"~/Bin/Judge.dll")來肯定物理途徑。ASP.NET中要應用DllImport的,必需在先“using System.Runtime.InteropServices;”不外,我發明,挪用這類"非托管Dll”相當的慢,能夠是由於我的辦法須要長途驗證吧,然則其實是太慢了。經由一翻研討,終究想到了一個完善的處理方法起首我們用


[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函數的地址,再經由過程這兩個函數來獲得我們的DLL外面的函數。
我們可以先用Server.MapPath(@"~/Bin/Judge.dll")來獲得我們的DLL的物理途徑,然後再用LoadLibrary停止載入,最初用GetProcAddress獲得要用的函數地址

以下自界說類的代碼完成LoadLibrary的裝載和函數挪用


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); 
        }       

        //將要履行的函數轉換為拜托 
        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函數

年夜家在現實任務進修C#的時刻,能夠會問:為何我們要為一些曾經存在的功效(好比Windows中的一些功效,C++中曾經編寫好的一些辦法)要從新編寫代碼,C#有無辦法可以直接都用這些本來曾經存在的功效呢?謎底是確定的,年夜家可以經由過程C#中的DllImport直接挪用這些功效。   
DllImport地點的名字空間 using System.Runtime.InteropServices;   
MSDN中對DllImportAttribute的說明是如許的:可將該屬性運用於辦法。DllImportAttribute 屬性供給對從非托管 DLL
導出的函數停止挪用所必須的信息。作為最低請求,必需供給包括進口點的 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具有單個定位參數:指定包括被導入辦法的 dll 稱號的
dllName 參數。    
3、DllImport具有五個定名參數: 
a、CallingConvention
參數指導進口點的挪用商定。假如未指定 CallingConvention,則應用默許值
CallingConvention.Winapi。
b、CharSet 參數指導用在進口點中的字符集。假如未指定 CharSet,則應用默許值
CharSet.Auto。       
c、EntryPoint 參數給出 dll 中進口點的稱號。假如未指定
EntryPoint,則應用辦法自己的稱號。         
d、ExactSpelling 參數指導 EntryPoint
能否必需與指導的進口點的拼寫完整婚配。假如未指定 ExactSpelling,則應用默許值 false。         
e、PreserveSig
參數指導辦法的簽名應該被保存照樣被轉換。當簽名被轉換時,它被轉換為一個具有 HRESULT前往值和該前往值的一個名為 retval
的附加輸入參數的簽名。假如未指定 PreserveSig,則應用默許值 true。         
f、SetLastError 參數指導辦法能否保存
Win32"上一毛病"。假如未指定 SetLastError,則應用默許值 false。       
4、它是一次性屬性類。     
  
5、另外,用 DllImport 屬性潤飾的辦法必需具有 extern 潤飾符。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved