在C#调用Native DLLs (P/Invoke)
在C#中,我们可以透过PInvoke(Platform Invocation Services)来access unmanaged DLL中的function, structs,甚至是callbacks function。
以下是一个简单的例子,示范如何在C#中调用Windows DLL user32.dll。
MessageBox在user32.dll声明如下:
- MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
C#程序范例:
- using System;
- using System.Runtime.InteropServices; // For StructLayout, DllImport
- class MsgBoxTest
- {
- [DllImport("user32.dll"]
- static extern int MessageBox(IntPtr hWnd, String text, String caption, int type);
- public static void Main()
- {
- MessageBox(IntPtr.Zero, "Text", "Caption", 0);
- }
- }
有三个地方要注意。DllImport定义function位于哪个dll中,static定义这是一个global method,extern则是告诉CLR此function是定义在外部文件中。
看到这边好像觉得P/Invoke没什么,继续看下去就知道P/Invoke为什么这么让人头痛。
如果Native function的参数是struct该怎么处理?让我们看一个例子:
- void GetSystemTime(LPSYSTEMTIME lpSystemTime);
- typedef struct _SYSTEMTIME {
- WORD wYear;
- WORD wMonth;
- WORD wDayOfWeek;
- WORD wDay;
- WORD wHour;
- WORD wMinute;
- WORD wSecond;
- WORD wMilliseconds;
- } SYSTEMTIME, *PSYSTEMTIME;
要调用这个function,我们必须定义一个C#的Class和C Struct有一样的结构。
- using System;
- using System.Runtime.InteropServices;
- [ StructLayout( LayoutKind.Sequential )]
- public class SystemTime
- {
- public ushort year;
- public ushort month;
- public ushort weekday;
- public ushort day;
- public ushort hour;
- public ushort minute;
- public ushort second;
- public ushort millisecond;
- }
StructLayout告诉marshaler如何把每个C# class中的field对应到C Struct中,LayoutKind.Sequential表示每个field是根据pack-size aligned sequentially。
默认的pack-size是8,也就是说所有的field都会aligned成8 bytes。我们可以在StructLayout中加入Pack attribute来修改pack-size。
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
GetSystemTime范例由于刚好是8 byte aligned所以不需更改pack size。
要调用GetSystemTime很简单:
- using System;
- using System.Runtime.InteropServices;
- class MsgBoxTest
- {
- [DllImport("Kernel32.dll")]
- public static extern void GetSystemTime(SystemTime st);
- public static void Main()
- {
- SystemTime t = new SystemTime();
- GetSystemTime(t);
- Console.WriteLine(t.Year);
- }
- }
如果不知道native function如何在C#中声明,可以去PINVOKE.NET搜索。此网站也提供一个方便的Visual Studio add-in可让你在VS中直接查询。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
