Win32 API:C++ 到 .NET






3.77/5 (40投票s)
2005年3月1日
12分钟阅读

412231
这是一份将 C++ API 调用转换为 .NET P/Invoke 的对照表。它包括数据类型转换和一些技巧。
引言
我正在撰写一篇文章,为那些需要在 .NET 程序中使用 API 导入来调用 C++ 函数的开发人员提供参考。我还没有找到一个看起来很好或者包含所有数据类型并正确转换的完整网站。所以,我决定自己写一个。我还建议,如果可用的话,使用任何与 API 功能相同的新的 .NET 函数。至少 75% 的 API 已经被转换为 .NET,并可在各种类中使用。这是因为它们通常工作得更好看,也更美观。如果您有任何问题,请给我发送电子邮件或发布到留言板上。
.NET API 声明形式
VB.NET
Declare Function <Name> Lib <dll name> <Optional fields> (<params>) _
As <return type>
C# 定义
[DllImport("<dll name>", <optional fields>)]
static extern <return type> <Method name> (<Params>)
托管 C++ .NET
[DllImport("<Dll name>",<optional fields>)]
static <return type> <Function name>( <Params>);
示例
C#、VB.NET 和 VB6 的 Windows API 参考 - 该网站包含 VB.NET、C#.NET 和一些 VB6 的所有主要 API 声明。
这是我使用这些网站制作的一个程序
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# 定义
[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)
托管 C++. NET
[DllImport("KERNEL32.DLL",EntryPoint="MoveFileW",
SetLastError=true,CharSet=CharSet::Unicode,ExactSpelling=true,
CallingConvention=CallingConvention::StdCall)]
static bool MoveFile( String^ src, String^ dst );
技巧
- 在此列表中,数据类型的指针表示为 P,例如
DWORD* = PDWORD
。 - 某些类型(如
UIntPtr
)不符合 CLS 规范,因此我使用IntPtr
代替,但您可以使用其中任何一种。 - 通常,IDE 的 Intellisense 中“=”后出现的第一个选项是最佳选择。
- 在 COM Interop 中使用字符串时,对于输入,您总是使用
string
来表示WCHAR*
、TCHAR*
等。对于输出,您可以使用string
或StringBuilder
,但有时您需要使用IntPtr
并使用Marshal.PtrToStructure()
从中封送字符,并递增指针直到遇到null
字符。要递增指针,请将其转换为int
,并每次按从Marshal.PtrToStructure()
获取的类型大小递增。例如:pointer += Marshal.SizeOf(<上次获取的对象>);
- 有时某些不正确的数据类型也会起作用。例如:
int
可以用于uint
。 - 如果您需要将
IntPtr
转换回int
或其他类,请使用Marshal.PtrToStructure()
或其他IntPtr
方法。 - 如果您使用的 API 依赖于 ANSI 或 Unicode,请确保选择正确的选项,以便正确格式化字符串。请查看 CharSet 枚举。
- 大多数 API 调用都可以用托管声明编写,但有些需要指针。在 C# 中,如果将代码用
unsafe
关键字括起来并使用/unsafe
编译器选项,则可以使用指针。 - 如果您想确保垃圾收集器不会在 API 调用中吞噬您的
IntPtr
,您可以使用HandleRef
类型。 - 当您需要为 API 声明
struct
时,请确保它们具有StructLayout.Sequential
属性。此外,有时您可能需要更改struct
的打包以使其正常工作,但通常不需要。 - 当向 API 方法传递或从 API 方法检索数组时,请查看它是指向数组的指针还是直接输入数组。如果是指针,您可能需要将其封送到
IntPtr
。 - 有时选择要使用的类型可能很困难,但经过几次尝试后您会掌握窍门的。
- 当我展示用于指向数据类型指针的类型时,我说是
IntPtr
或它指向的数据类型,有时你可以直接说ref <datatype>
或out <datatype>
,但除非它是输入char *
,否则对于输入你需要使用IntPr
,对于输出你需要使用ref IntPtr
。 - 如果您的函数声明未能工作,请不要总是归咎于您编写声明的方式,它可能是之前的方法调用弄乱了它,或者只是传入了错误的数据。
- 仅在必要时才使用
Marshal
和MarshalAs
类,因为在某些情况下它们会占用更多的处理能力。
数据类型转换表:C++ 到 .NET
术语 |
描述 |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
|
|
.NET =
|
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ =
|
|
.NET = C++ =
|
|
.NET = C++ = |
|
.NET =
C++ =
C++ = |
|
.NET =
C++ =
C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET = C++ = |
|
.NET =
|
|
.NET = C++ = |
|
.NET = default 为标准,请查看
|
|
.NET = C++ = |
|
.NET = C++ = |