LayoutKind 枚举: 控制当导出到非托管代码时对象的布局。
成员:
成员名称
|
说明
|
Auto
|
运行库自动为非托管内存中的对象的成员选择适当的布局。使用此枚举成员定义的对象不能在托管代码的外部公开。尝试这样做将引发异常。
|
Explicit
|
对象的各个成员在非托管内存中的精确位置被显式控制。每个成员必须使用 FieldOffsetAttribute 指示该字段在类型中的位置。
|
Sequential
|
对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。这些成员根据在 StructLayoutAttribute.Pack 中指定的封装进行布局,并且可以是不连续的。
|
此枚举与 StructLayoutAttribute 一起使用。默认情况下,公共语言运行库将使用 Auto 布局值。为减少与 Auto 值关联的布局相关问题,C#、Visual Basic 和 C++ 编译器为值类型指定了 Sequential 布局。
示例:参数中有回调函数的WINAPI 函数在托管环境中的调用
(其中createThread (…) 函数中第三个参数就需要调用自定义的WINAPI 函数)
//非托管函数的托管调用声明
[StructLayout(LayoutKind.Sequential)] //在本例中没有用到它.
public struct SECURITY_ATTRIBUTES
{
uint nLength;
IntPtr lpSecurityDescriptor;
UInt32 bInheritHandle;
} ;
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateEvent(IntPtr lpEventAttributes, Boolean bManualReset, Boolean bInitialState, [MarshalAs(UnmanagedType.LPStr)] String lpName);
[DllImport("kernel32")]
public static extern IntPtr CreateThread(
IntPtr lpThreadAttributes,
uint dwStackSize,
ThreadProc lpStartAddress, // ThreadProc as friendly delegate
IntPtr lpParameter,
uint dwCreationFlags,
out uint dwThreadId);
//函数原型可参看msdn
定义:自定义WINAPI函数在托管环境下的声明
//stdcall //c++中的 自定义的WINAPI 函数: DWORD WINAPI Fun1Proc(LPVOID lpParameter)
static int Fun1Proc(IntPtr lpParameter)
{
MessageBox.Show ("thread is running");
return 0;
}
// Thread proc, to be used with Create*Thread
public delegate int ThreadProc(IntPtr param);
//使用:
using DWORD =System.Int32 ;
using WORD =System.Int16 ;
using HANDLE = System.IntPtr;
using HWND = System.IntPtr;
using HDC = System.IntPtr;
using PVOID = System.IntPtr;
using LPVOID = System.IntPtr;
HANDLE hThread=IntPtr.Zero;
uint x = 0;
ThreadProc proc = new ThreadProc(Fun1Proc);
hThread = CreateThread(
IntPtr.Zero,
0,
proc, hEvent,
0, // flags
out x);
WaitForSingleObject (hThread,unchecked((uint)-1));
CloseHandle (hThread);
MessageBox.Show ( "main thread is running" );
//CreateEvent 函数原型
//CreateEvent, Win API, as implemented in kernel32.dll:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
//WINAPI 函数在托管环境下的声明示例
[DllImport("kernel32.dll, SetLastError=true ")]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes,
bool bManualReset, bool bInitialState,
[MarshalAs(UnmanagedType.LPStr) string lpName);
VB.NET
Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA"(_
ByVal dwFlags As Integer, ByRef lpSource As Object, _
ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, _
ByVal lpBuffer As String, ByVal nSize As Integer, _
ByRef Arguments As Integer) As Integer
C# definition
[DllImport("kernel32.dll", SetLastError=true)]
static extern int FormatMessageA ( int dwFlags, ref object lpSource,
int dwMessageId, int dwLanguageId, string lpBuffer,
int nSize, ref int Arguments)
Managed C++. NET
[DllImport("KERNEL32.DLL",EntryPoint="MoveFileW",
SetLastError=true,CharSet=CharSet::Unicode,ExactSpelling=true,
CallingConvention=CallingConvention::StdCall)]
static bool MoveFile( String^ src, String^ dst );
更为详细的介绍请看:
WIN API查看器
http://www.codeproject.com/csharp/APIBrowser.asp
<<A Closer Look at Platform Invoke>>
<<Marshaling Data with Platform Invoke>>
附录1:Windows Data Type 与 .NET Data Type 的对应关系
Windows Data Type
|
.NET Data Type
|
BOOL, BOOLEAN
|
Boolean or Int32
|
BSTR
|
String
|
BYTE
|
Byte
|
CHAR
|
Char
|
DOUBLE
|
Double
|
DWORD
|
Int32 or UInt32
|
FLOAT
|
Single
|
HANDLE (and all other handle types, such as HFONT and HMENU)
|
IntPtr, UintPtr or HandleRef
|
HRESULT
|
Int32 or UInt32
|
INT
|
Int32
|
LANGID
|
Int16 or UInt16
|
LCID
|
Int32 or UInt32
|
LONG
|
Int32
|
LPARAM
|
IntPtr, UintPtr or Object
|
LPCSTR
|
String
|
LPCTSTR
|
String
|
LPCWSTR
|
String
|
LPSTR
|
String or StringBuilder*
|
LPTSTR
|
String or StringBuilder
|
LPWSTR
|
String or StringBuilder
|
LPVOID
|
IntPtr, UintPtr or Object
|
LRESULT
|
IntPtr
|
SAFEARRAY
|
.NET array type
|
SHORT
|
Int16
|
TCHAR
|
Char
|
UCHAR
|
SByte
|
UINT
|
Int32 or UInt32
|
ULONG
|
Int32 or UInt32
|
VARIANT
|
Object
|
VARIANT_BOOL
|
Boolean
|
WCHAR
|
Char
|
WORD
|
Int16 or UInt16
|
WPARAM
|
IntPtr, UintPtr or Object
|
附录2: 托管数据类型与非托管数据类型对比表
Unmanaged type in Wtypes.h
|
Unmanaged C language type
|
Managed class name
|
Description
|
HANDLE
|
void*
|
32 bits
|
|
BYTE
|
unsigned char
|
8 bits
|
|
SHORT
|
short
|
16 bits
|
|
WORD
|
unsigned short
|
16 bits
|
|
INT
|
int
|
32 bits
|
|
UINT
|
unsigned int
|
32 bits
|
|
LONG
|
long
|
32 bits
|
|
BOOL
|
long
|
32 bits
|
|
DWORD
|
unsigned long
|
32 bits
|
|
ULONG
|
unsigned long
|
32 bits
|
|
CHAR
|
char
|
Decorate with ANSI.
|
|
LPSTR
|
char*
|
Decorate with ANSI.
|
|
LPCSTR
|
Const char*
|
Decorate with ANSI.
|
|
LPWSTR
|
wchar_t*
|
Decorate with Unicode.
|
|
LPCWSTR
|
Const wchar_t*
|
Decorate with Unicode.
|
|
FLOAT
|
Float
|
32 bits
|
|
DOUBLE
|
Double
|
64 bits
|
附录3: C/C++与C#的数据类型对应关系
C/C++
|
C#
|
HANDLE, LPDWORD, LPVOID, void*
|
IntPtr
|
LPCTSTR, LPCTSTR, LPSTR, char*, const char*, Wchar_t*, LPWSTR
|
String [in], StringBuilder [in, out]
|
DWORD, unsigned long, Ulong
|
UInt32, [MarshalAs(UnmanagedType.U4)]
|
bool
|
bool
|
LP<struct>
|
[In] ref <struct>
|
SIZE_T
|
uint
|
LPDWORD
|
out uint
|
LPTSTR
|
[Out] StringBuilder
|
PULARGE_INTEGER
|
out ulong
|
WORD
|
uInt16
|
Byte, unsigned char
|
byte
|
Short
|
Int16
|
Long, int
|
Int32
|
float
|
single
|
double
|
double
|
NULL pointer
|
IntPtr.Zero
|
Uint
|
Uint32
|
当结构体中是一个数据类型指针时,采用.net对应的数据类型替换.
当结构体中的变量是另一个结构体的指针时,采用IntPtr类型来操作.