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

DLLImport在C#中的用法

編輯:C#基礎知識
    上網搜了一下,最常見的就是使用它來調用WIN32的API,例如上面所示。或者調用一下C或C++編寫的DLL。 這東西沒怎麼用過。只是前幾 天忽然分配下一個臨時的任務,做一個“停車廠管理”的小東西,聽說是一個大干部的小孩子要弄這麼個東西,那干部是公司的客戶,討論正經事之余又拜托了我們 做這麼個小東西。其中用到了單片機模擬車輛出入的一些信號。 
    MSDN中對DllImportAttribute的解釋是這樣的:可將該屬性應用於方法。DllImportAttribute 屬性提供對從非托管 DLL 導出的函數進行調用所必需的信息。作為最低要求,必須提供包含入口點的 DLL 的名稱。 
並給了一個示例: 
[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW",  SetLastError=true, 
CharSet=CharSet.Unicode, ExactSpelling=true, 
CallingConvention=CallingConvention.StdCall)] 
public static extern bool MoveFile(String src, String dst);

我 對單片機一竅不通,好在有人寫好了輪詢單片機的DLL,我只管調用,由於是C++寫的,於是將DLL拷貝到BIN目錄後(這DLLImport會從程序啟 動目錄開始查找相應名稱的DLL,未找到則轉至system32下查找),用DllImport來調用,但在這個過程中遇到了幾個問題:
 
1.看了一下C++的代碼,需要用到的只有三個方法:
bool OpenSerialPort1()
bool fnGetIO(unsigned char& P1, unsigned char& P2, unsigned char& P3)
bool CloseSerialPort1()

 

 

於是就在自己的程序中寫了:

using System.Runtime.InteropServices;
……
[DllImport("GetIODll.dll", EntryPoint = "OpenSerialPort1")]
public static extern bool OpenSerialPort1();
[DllImport("GetIODll.dll", EntryPoint = "fnGetIO")]
public static extern bool fnGetIO(ref byte P1, ref byte P2, ref byte P3);
[DllImport("GetIODll.dll", EntryPoint = "CloseSerialPort1")]
public static extern bool CloseSerialPort1();

 


然而程序在運行時無論如何總是提示“找不到入口點”,搞得懵了,只好上網搜去,最後下了一個叫eXeScope的小軟件,裝完之後查看該DLL,果然如貼子中寫的,DLL中的函數名稱發生了變化,分別成了:
?OpenSerialPort1@@YA_NXZ
?fnGetIO@@YA_NAAE00@Z
?CloseSerialPort1@@YA_NXZ
將這些怪怪的名稱代入到EntryPoin中,編譯運行,沒有問題了。
 
2. 可是接上單片機之後,問題又來了,雖然OpenSerialPort1返回的結果是true,但fnGetIO讀出一數據全是0,按理應該是全1才對。來 了一個同事,說反正有源碼,把原來的DLL弄成標准C的試試,標准C不標准C的我也沒明白,讓那人給改了一下,把編譯之後的DLL拷到自己程序的BIN 下,將EntryPoin換成正常的函數名,運行,這回是真的OK了。
 

讀寫.ini文件時,也會用到DllImport,不過現在.ini文件好像用得少了,下面是讀寫的程序:

{
publicstring path; 
[DllImport("kernel32")]
privatestaticexternlong WritePrivateProfileString(string section,string key,string val,string filePath);
[DllImport("kernel32")]
privatestaticexternint GetPrivateProfileString(string section,string key,string def,StringBuilder 
retVal,int size,string filePath);
public IniFile(string INIPath)
{
       path = INIPath;
}
publicvoid IniWriteValue(string Section,string Key,string Value)
{
       WritePrivateProfileString(Section,Key,Value,this.path);
}
publicstring IniReadValue(string Section,string Key)
{
       StringBuilder temp = new StringBuilder(255);
       int i = GetPrivateProfileString(Section,Key,"",temp,255,this.path);
       return temp.ToString();
}
}

 

 
網上關於DllImport的很多問題是由於所調方法的參數比較復雜,現在我還沒用到,看到一篇貼子,參數中帶指針的,也先錄下來,以備將來查用: 
參數是用指針來獲取一個數組:Int GetData(byte * pBuffer)   
pBuffer是數組的首地址,也就是說GetData會寫pBuffer[0],pBuffer[1]....pBuffer[100]; 
答曰:
[DllImport("yourDllFile.dll"]   
Private static extern int GetValue([MarshalAs(UnmanagedType.LPArray)]byte[] pValue);

 

如果是out參數,可以如下   

[DllImport("yourDllFile.dll")]   
Private static extern int GetValue([Out,MarshalAs(UnmanagedType.LPArray)]byte[] pValue);

 

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