形如windows api函数:
BOOL MessageBeep( UINT uType // beep type );
c#托管引用声明格式如下:
[DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);
其不是函数定义也不是函数调用而只是声明。
static:这是 P/Invoke 方法所要求的,因为在该 Windows API 中没有一致的实例概念。
extern:提示编译器该方法是通过一个从 DLL 导出的函数实现的,因此不需要提供方法体。
[DllImport("User32.dll")]:P/Invoke 方法只是元数据,实时 (JIT) 编译器在运行时通过它将托管代码与非托管的 DLL 函数连接起来。执行这种到非托管世界的连接所需的一个重要信息就是导出非托管方法的 DLL 的名称。
数据类型变换:C# 的规则之一是它的调用语法只能访问 CLR 数据类型。CLR 类型和 Win32 之间在样式上有很大的不同。
DllImportAttribute 属性:指出宿主 DLL 、EntryPoint、CharSet、SetLastError 和 CallingConvention。
EntryPoint: 不希望外部托管方法具有与 DLL 导出相同的名称。
CharSet :如果 DLL 函数不以任何方式处理文本,则可以忽略 DllImportAttribute 的 CharSet 属性。然而,当 Char 或 String 数据是等式的一部分时,应该将 CharSet 属性设置为 CharSet.Auto。当然,明确dll函数的编码要求就显示的CharSet.Ansi 或 CharSet.Unicode 了。
SetLastError:使用 GetLastError 来查找扩展的错误信息,则应该在外部方法的 DllImportAttribute 中将 SetLastError 属性设置为 true。
CallingConvention :此属性,可以给 CLR 指示应该将哪种函数调用约定用于堆栈中的参数。CallingConvention.Winapi 的默认值是最好的选择。
数据封送处理:
Win32 Types | Specification | CLR Type |
---|---|---|
char, INT8, SBYTE, CHAR†| 8-bit signed integer | System.SByte |
short, short int, INT16, SHORT | 16-bit signed integer | System.Int16 |
int, long, long int, INT32, LONG32, BOOL†, INT | 32-bit signed integer | System.Int32 |
__int64, INT64, LONGLONG | 64-bit signed integer | System.Int64 |
unsigned char, UINT8, UCHAR†, BYTE | 8-bit unsigned integer | System.Byte |
unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR†, __wchar_t | 16-bit unsigned integer | System.UInt16 |
unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT | 32-bit unsigned integer | System.UInt32 |
unsigned __int64, UINT64, DWORDLONG, ULONGLONG | 64-bit unsigned integer | System.UInt64 |
float, FLOAT | Single-precision floating point | System.Single |
double, long double, DOUBLE | Double-precision floating point | System.Double |