標籤:
一 調用格式
C#在調用windowsAPI函數介面的時候有一套專門的調用流程
首先我們在調用API函數的時候必須引用命名空間InteropServices
using System.Runtime.InteropServices;
例如我們想調用windows的kernel32.dll動態庫中的介面函數中的AllocConsole()控制台函數介面
下面我們用最簡單的調用形式來聲明調用此函數介面(空方法,即方法體為空白)
[DllImport("kernel32.dll")]
public static extern bool AllocConsole();
下面我們可以用DllImportAttribute特性添加欄位進一步說明
1 CallingConvention
指示向非託管實現傳遞方法參數時所用的CallingConvention值
CallingConvention.Cded:調用方清理堆棧。他使用你能夠調用具有varargs的函數
CallingConvention.StdCall:被呼叫者清理堆棧。他是從Managed 程式碼調用非託管函數的預設約定
2 CharSet
控制調用函數的名稱版本及指示如何向方法封送String參數
CharSet.Ansi:所有字串轉換成ANSI字串,同時向DLL EnterPoint的名稱中追加字母”A“
CharSet.Unicode:所有字串參數在傳遞到非託管實現之前都轉換成Unicode字元;向DLL EnterPoint的名稱中追加字母"W"
CharSet.Auto:這種轉換就與平台有關(例如在windows NT上位unicode,而在windows 98上為Ansi)。
CharSet的預設值為Ansi
3 EnterPoint
指示要調用的DLL進入點的名稱或序號
如果你的方法名不想與api函數同名的話,一定要指定此參數
例如我想調用user32.dll中的MessageBox函數但是我想以自己的名字MsgBox名字來命名的話
[DllImport("user32.dll",CharSet="CharSet.Auto",EnterPoint="MessageBox")]
public static extern int MsgBox(IntPtr hWnd,string txt,string caption,int type);
4 ExactSpelling
指示是否應修改非託管DLL中的進入點的名稱,與CharSet欄位中指定的CharSet值相對應。
如果為true,則當DllImportAttribute.CharSet欄位設定為CharSet的Ansi值時,向方法名稱中追加字母”A“,當DllImportAttribute.CharSet欄位設定為CharSet的unicode值時,同方法名稱中追加字母”W“,此欄位的預設值為false
5 PreserveSig
指示託管方法簽名不應該轉換成返回HRESULT,並且可能有一個對應傳回值的附加[out,retval]參數的非託管簽名
6 SerLastError
指示被呼叫者法從屬性化方法傳回值之前調用win32 API SetLastError。
true指示調用方將調用SetLastError,預設為false。運行時封送拆收器調用GetLastError並緩衝返回的值,以防其他API調用重寫。
二 參數類型轉換
| C++ |
C# |
| DWORD |
int |
| WORD |
Int16 |
| 字串指標類型 |
string |
| 控制代碼(handle、hWnd) |
IntPtr |
| 結構或者類 |
要先用StructLayout特性限定聲明結構或類 |
1 Explicit
用於控制每個資料成員的精確位置。利用Explicit,每個成員必須使用FieldOffsetAttribute指示此欄位在類型中的位置:
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime
{
[FieldOffset(0)]public ushort wYear;
[FieldOffset(2)]public ushort wMonth;
[FieldOffset(4)]public ushort wDayOfWeek;
[FieldOffset(6)]public ushort wDay;
[FieldOffset(8)]public ushort wHour;
[FieldOffset(10)]public ushort wMinute;
[FieldOffset(12)]public ushort wSecond;
[FieldOffset(14)]public ushort wMilliseconds;
}
2 Sequential
用於強制將成員按出現的順序進行循序配置
例如針對API中的OSVERSIONINFO結構,在.net中定義類或者結構的例子如下
API原型
* API中定義原結構聲明
* OSVERSIONINFOA STRUCT
* dwOSVersionInfoSize DWORD ?
* dwMajorVersion DWORD ?
* dwMinorVersion DWORD ?
* dwBuildNumber DWORD ?
* dwPlatformId DWORD ?
* szCSDVersion BYTE 128 dup (?)
* OSVERSIONINFOA ENDS
*
* OSVERSIONINFO equ <OSVERSIONINFOA>
在.net中聲明如下
[ StructLayout( LayoutKind.Sequential )]
public class OSVersionInfo
{
public int OSVersionInfoSize;
public int majorVersion;
public int minorVersion;
public int buildNumber;
public int platformId;
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]
public String versionString;
}
注意:結構作為參數的時候,一般前面要加上ref修飾符,否則會出現錯誤:對象的引用沒有指定對象的執行個體
原文請訪問:http://www.jb51.net/article/46041.htm
C#調用windowsAPI函數