程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET Compact Framework下Win32 API P/Invoke的使用

.NET Compact Framework下Win32 API P/Invoke的使用

編輯:關於.NET

由於CF是一個精簡(Compact)的.NET Framework,因此在開發CF應用時有一部分功能MS並沒有在CF中實現,需要直接調用Win32的API來實現。由於Win32的API是面向native代碼的,一般會提供一個DLL庫以及相應header文件。使用C++是十分容易和簡單調用這些API,但是使用C# .NET就沒那麼幸運了。C#調用Win32的API往往要借助於P/Invoke的幫助,下面講述一下P/Invoke 的使用。

API的引入

調用Win32的API需要引入相應的DLL,Wince下大部分的API存在於coredll.dll裡面,同時DllImport不僅僅支持Win32 API,他可以支持任何native 的DLL的引入。

[DllImport("coredll.dll", CharSet = CharSet.Auto)]

錯誤情況處理

調用Win32的API一般通過返回值表示調用結果,推薦使用Exception代替返回值的方式表達錯誤和異常情況。

int lStatus = RasHangUp(rasSession);
if (lStatus != 0)
{
  throw new ApplicationException("RasHangUp(" + rasSession + ") failed with error code: " + lStatus);
}

參數的轉換

調用Win32的API大部分工作就是在對調用參數進行類型轉換,這些參數基於.NET的角度叫做unmanaged type(native type),對應於.NET built-in 的managed type.例如調用查詢所有WiFi網卡信息的接口,入口參數為LPWSTR和PINTFS_KEY_TABLE,LPWSTR是字符串指針( Long Pointer to Wide String),而PINTFS_KEY_TABLE是一個結構體。

DWORD WZCEnumInterfaces(
LPWSTR pSrvAddr,
PINTFS_KEY_TABLE pIntfs
);
typedef struct{ DWORD dwNumIntfs; PINTF_KEY_ENTRY pIntfs;} INTFS_KEY_TABLE, *PINTFS_KEY_TABLE;

在CF.NET中會轉化成下面接口,其中INTFS_KEY_TABLE為一個自定義的結構體。

[DllImport("wzcsapi.dll")]
public static extern uint WZCEnumInterfaces(string pSrvAddr, ref INTFS_KEY_TABLE pIntfs);
public struct INTFS_KEY_TABLE : IDisposable
{
private uint dwNumIntfs;
public IntPtr pIntfs;
public INTFS_KEY_TABLE(uint size)
{
this.dwNumIntfs = size;
if (size != 0)
{
this.pIntfs = Marshal.AllocHGlobal((int)(Marshal.SizeOf(typeof(IntPtr)) * size));
}
else
{
this.pIntfs = IntPtr.Zero;
}
}
public string this[uint i]
{
get
{
return Marshal.PtrToStringUni((IntPtr)Marshal.ReadInt32(this.pIntfs, (int)(i * 4)));
}
}
public uint Count
{
get
{
return this.dwNumIntfs;
}
}
public void Dispose()
{
if (this.pIntfs != IntPtr.Zero)
{
Marshal.FreeHGlobal(this.pIntfs);
}
}
}

所有類型轉換都是基於基本類型,所以要進行類型轉換要從基本類型入手。

c++ int類型(int, short, long, uint)直接轉

c++ float類型(double, float)直接轉

byte轉成uint

bool要轉成int

enum轉成uint

public enum INTF_FLAGS : uint
{
INTF_ALL = 0xffffffff,
INTF_ALL_FLAGS = 0x0000ffff,
/// <summary>
/// mask for the configuration mode (NDIS_802_11_NETWORK_INFRASTRUCTURE value)
/// </summary>
INTF_CM_MASK = 0x00000007,
}

char不能轉,因為c++裡面的char是1byte,而.NET是2bytes

對於結構體的轉換可以自定義一個結構,例如上列子的INTFS_KEY_TABLE。如果結構體裡面還包含結構體可以使用byte[]或者IntPtr來表示,因為c++裡面的struct就是內存加上offset。

這些我做P/Invoke找到的一些規律,但是發現不同API,轉換還是有點不一樣,上面只是列出一般情況,特殊情況還要根據列子進行調整。

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