__stdcal 约定时,函数参数按照从右 到 左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。MSDN 如下说 明: 成员名 称 Cdecl 说明 调用方清理堆栈。这使您能够调用具有 varargs 的函数(如 Printf),使 之可用于接受可变数目的参数的方法。
FastCall 不支持此调用约定。 StdCall 被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。
ThisCall 第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈 上。此调用约定用于对从非托管 DLL 导出的类调用方法。 Winapi 此成员实际上不是调用约定,而是使用了默认平台调用约定。例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。
3、注意事项: 参 数个数、顺序、类型必须保持“等价”一致,函数名称和参数名称可以不一致。
二、 参数封送:字符串 可以说新手使用 P-INVOKE 最开始的头疼就是 C#和 C++的字符串传递,由于不同编程语言对 字符串处理的机制不同, 因此导致托管代码的平台调用必须对字符串进行特殊的封送处理。本 节将阐述以下几个
问题: (1)、C#的 string 和 C++的字符串首指针如何对应 (2)、字符串还有 ANSI 和 UNICODE(宽字符串)之分 (3)、封送字符串数组 1、通过 CharSet 字段控制字符串封送行为: C++: void void __cdecl TestString1(char* hello);
__cdecl TestString2(const wchar_t* str,wchar_t* outStr,int size);
MSDN 上给出 C/C++字符串类型与 C#字符串类型的对应关系
Wtypes.h 中类型 CHAR LPSTR 用 ANSI 修饰。 LPCSTR 用 ANSI 修饰。 LPWSTR 用 Unicode 修饰。 LPC
WSTR 用 Unicode 修饰。 C#
非托管 C/C++ char char*
托管类名 System.Char
说明 用 ANSI 修饰。
System.String 或 System.Text.StringBuilder
Const char*
System.String 或 System.Text.StringBuilder
wchar_t*
System.String 或 System.Text.StringBuilder
Const wchar_t*
System.String 或 System.Text.StringBuilder
[DllImport("test.dll", EntryPoint = "TestString1", CharSet =CharSet.Ansi)] public static extern voidTestString1(string hello);
[DllImport("test.dll", EntryPoint = "TestString1", CharSet =CharSet.Unicode)] public static extern voidTestString2(stringstr,StringBuilder outStr,int size) 2、使用 MarshalAs 属性控制字符串封送行为: CharSet 字段影响的是整个函数过程的字符串封送行为, MarshalAs 属性只影响其作用 的字符串参数。因此,当一个非托管函数的参数即由 ANSI 字符串,又有 Unicode 字符串时, 就只能用 MarshalAs 属性来控制封送行为。 C++: void __cdecl TestString3(const char* str1,const wchar_t* str2,wchar_t* outStr,int size); MSDN 给出 MarshalAs 属性控制字符串封送行为: 枚举类型 非托管格式说明 UnmanagedType.AnsiBStr 长度前缀为双字节的 Unicode 字符的 COM 样式的 BSTR。。 UnmanagedType.LPStr 单字节、null 空终止的 ANSI 字符数组的指针。(默认值)
UnmanagedType.LPTStr null 空终止与平台相关的字符数组的指针。 UnmanagedType.LPWStr null 空终止与 Unicode 的字符数组的指针。 UnmanagedType.TBStr 一个有长度前缀的与平台相关的 COM 样式的 BSTR。 需要注意的是:此表只适用于 string 类型,对于 StringBuilder 而言,能够允许的选项只有: LPStr、LPTStr、LPWStr。 C#: [DllImport("test.dll", EntryPoint = "TestString3")] public static extern voidTestString3( [MarshalAs(UnmanagedType.LPStr)]string str1, [MarshalAs(UnmanagedType.LPWStr)]string str2, [MarshalAs(UnmanagedType.LPWStr)]stringoutStr,int size); 3、封送作为返回值的字符串: C++: char* __cdecl GetStringReturn1(); GetStringReturn2();
wchar_t*__cdecl
这里,有两