Win32 API: C++ to .NET

Introduction

I am writing an article to give a reference to developers who need to use API imports in their .NET programs to call C++ functions. I haven't found a single site that looks good or is totally complete with all the data types or has them converted correctly. So, I decided to write one. I also recommend using any new .NET function that does the same thing as an API if it is available. At least 75% of the API has already been converted to .NET and is available in various classes. This is because they usually work better and look nicer. If you have any questions send me an email or post them to the message board.

我在写一篇文章,给那些需要使用API导入在他们的.net程序中调用c++函数 的开发者一个参考。我一直没有找到一家网站,能够很好的或是完全的将所有的数据类型解释清楚或是转换正确。因此,我决定写一篇。我一直建议使用一些新的.net函数去做相同的事情,就像是API函数,当然如果方便的话。最低75%的API函数已经转换成为.net代码,而且可以利用在各种类中。由于他们经常工作和使用的很好。

.NET API declaration form

VB.NET
Declare Function <Name> Lib <dll name> <Optional fields> (<params>) _
                                                      As <return type>
C# definition
[DllImport("<dll name>", <optional fields>)] 
        static extern <return type> <Method name> (<Params>)
Managed C++ .NET
[DllImport("<Dll name>",<optional fields>)]
     static <return type> <Function name>( <Params>);

Examples

Windows API reference for C#, VB.NET & VB6 - This site has every major API declaration for VB.NET, C#.NET and some VB6.

Here is a program I have made that uses these sites:

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 );

Tips

  1. In this list, a pointer to a data type is represented like P, for example DWORD* = PDWORD.(在下面的列表中,一个指针数据类型可能会以像P字符这样表示)
  2. Some types like UIntPtr are not CLS compliant so I use IntPtr instead, but you can use any of these.(一些类型,像UIntPtr并不符合公共规范,所以我使用IntPtr来替换,但是你可以使用这些)
  3. The first choice that comes up after the "=" in the IDE�s Intellisense is the best choice usually.(首先来自于IDE编译器的智能选择,当问题出现在“=”号之后时)
  4. When using strings in COM Interop, for inputs you always use string for WCHAR*TCHAR*, etc. For outputs you can use stringor StringBuilder, but sometimes you need to use an IntPtr and marshal the characters out of it usingMarshal.PtrToStructure() and increment the pointer till you get null characters. To increment a pointer turn it into an intand increase the size each time by the size of the type you get from Marshal.PtrToStructure() each time. E.g. : pointer += Marshal.SizeOf(<last object you got back>);
  5. Sometimes certain data types that aren't correct will work. E.g.: An int could be used for a uint.
  6. If you need to convert an IntPtr back to an int or some other class, use Marshal.PtrToStructure() or some otherIntPtr method.
  7. If the API your using is dependent on ANSI or Unicode, make sure you select the correct one so that your strings will be formatted correctly. Look at the CharSet enumeration.
  8. Most of the API calls can be written in a managed declaration, but some need pointers, in C# you can use pointers if you surround the code with the unsafe keyword and use the /unsafe compiler option.
  9. If you want to make sure that the garbage collector doesn't eat your IntPtr in an API call you can use a HandleRef type.
  10. When you need to declare structs for API, make sure they have the StructLayout.Sequential attribute. Also sometimes you may need to change the packing on a struct to make it work right, but usually you don't.
  11. When passing or retrieving arrays to/from API methods, look if it's a pointer to an array or a direct input array, if it's a pointer you need to marshal it to an IntPtr possibly.
  12. Sometimes choosing the type to use can be hard but you'll get the hang of it after a few times.
  13. When I show the types to use for pointers to data types I say IntPtr or the data type it points to, sometimes you can just sayref <datatype> or out <datatype>, but unless it's an input char * you need to use IntPr for inputs and ref IntPtr for outputs.
  14. If your function declaration fails to work don't always blame it on the way you wrote declaration, it may be a call to the previous methods that messed it up, or just a bad data getting passed in.
  15. Use the Marshal and MarshalAs classes only when you have to, as they take up more processing power in certain situations.

Data type conversion sheet : C++ to .NET

Term

Description

ATOM

.NET = ushort

C++ = typedef WORD ATOM;

BOOL

.NET = bool or int

C++ = typedef int BOOL;

BOOLEAN

.NET = bool or byte

C++ = typedef BYTE BOOLEAN;

BYTE

.NET = byte

C++ = typedef unsigned char BYTE;

CALLBACK

.NET = delegate

C++ = #define CALLBACK __stdcall

CHAR

.NET = char

C++ = typedef char CHAR;

COLORREF

.NET = uint

C++ = typedef DWORD COLORREF;

CONST

.NET = const

C++ = #define CONST const

DWORD

.NET = uint

C++ = typedef unsigned long DWORD;

DWORDLONG

ulong

C++ = typedef ULONGLONG DWORDLONG;

DWORD_PTR

DWORD *

.NET = uint or IntPtr

C++ = typedef ULONG_PTR DWORD_PTR;

DWORD32

.NET = uint

C++ = typedef unsigned int DWORD32;

DWORD64

.NET = ulong

C++ = typedef unsigned __int64 DWORD64;

FLOAT

.NET = single

C++ = typedef float FLOAT;

HACCEL

.NET = IntPtr

C++ = typedef HANDLE HACCEL;

HANDLE

.NET = IntPtr

C++ = typedef PVOID HANDLE;

HBITMAP

.NET = IntPtr

C++ = typedef HANDLE HBITMAP;

HBRUSH

.NET = IntPtr

C++ = typedef HANDLE HBRUSH;

HCOLORSPACE

.NET = IntPtr

C++ = if(WINVER >= 0x0400)

C++ = typedef HANDLE HCOLORSPACE;

HCONV

.NET = IntPtr

C++ = typedef HANDLE HCONV;

HCONVLIST

.NET = IntPtr

C++ = typedef HANDLE HCONVLIST;

HCURSOR

.NET = IntPtr

C++ = typedef HICON HCURSOR;

HDC

.NET = IntPtr

C++ = typedef HANDLE HDC;

HDDEDATA

.NET = IntPtr

C++ = typedef HANDLE HDDEDATA;

HDESK

.NET = IntPtr

C++ = typedef HANDLE HDESK;

HDROP

.NET = IntPtr

C++ = typedef HANDLE HDROP;

HDWP

.NET = IntPtr

C++ = typedef HANDLE HDWP;

HENHMETAFILE

.NET = IntPtr

C++ = typedef HANDLE HENHMETAFILE;

HFILE

.NET = int

C++ = typedef int HFILE;

HFONT

.NET = IntPtr

C++ = typedef HANDLE HFONT;

HGDIOBJ

.NET = IntPtr

C++ = typedef HANDLE HGDIOBJ;

HGLOBAL

.NET = IntPtr

C++ = typedef HANDLE HGLOBAL;

HHOOK

.NET = IntPtr

C++ = typedef HANDLE HHOOK;

HICON

.NET = IntPtr

C++ = typedef HANDLE HICON;

HINSTANCE

.NET = IntPtr

C++ = typedef HANDLE HINSTANCE;

HKEY

.NET = IntPtr

C++ = typedef HANDLE HKEY;

HKL

.NET = IntPtr

C++ = typedef HANDLE HKL;

HLOCAL

.NET = IntPtr

C++ = typedef HANDLE HLOCAL;

HMENU

.NET = IntPtr

C++ = typedef HANDLE HMENU;

HMETAFILE

.NET = IntPtr

C++ = typedef HANDLE HMETAFILE;

HMODULE

.NET = IntPtr

C++ = typedef HINSTANCE HMODULE;

HMONITOR

.NET = IntPtr

if(WINVER >= 0x0500)

C++ = typedef HANDLE HMONITOR;

HPALETTE

.NET = IntPtr

C++ = typedef HANDLE HPALETTE;

HPEN

.NET = IntPtr

C++ = typedef HANDLE HPEN;

HRESULT

.NET = int or uint

C++ = typedef LONG HRESULT;

HRGN

.NET = IntPtr

C++ = typedef HANDLE HRGN;

HRSRC

.NET = IntPtr

C++ = typedef HANDLE HRSRC;

HSZ

.NET = IntPtr

C++ = typedef HANDLE HSZ;

HWINSTA

.NET = IntPtr

C++ = typedef HANDLE WINSTA;

HWND

.NET = IntPtr

C++ = typedef HANDLE HWND;

INT

.NET = int

C++ = typedef int INT;

INT_PTR

.NET = IntPtr

#if defined(_WIN64)

C++ = typedef __int64 INT_PTR;

#else

C++ = typedef int INT_PTR;

INT32

.NET = int

C++ = typedef signed int INT32;

INT64

.NET = long

C++ = typedef signed __int64 INT64;

LANGID

.NET = ushort or int

C++ = typedef WORD LANGID;

LCID

.NET = uint

C++ = typedef DWORD LCID;

LCTYPE

.NET = uint

C++ = typedef DWORD LCTYPE;

LGRPID

.NET = uint

C++ = typedef DWORD LGRPID;

LONG

.NET = int

C++ = typedef long LONG;

LONGLONG

.NET = long

#if !defined(_M_IX86)

C++ = typedef __int64 LONGLONG;

#else

C++ = typedef double LONGLONG;

LONG_PTR

.NET = IntPtr

#if defined(_WIN64)

C++ = typedef __int64 LONG_PTR;

#else

C++ = typedef long LONG_PTR;

LONG32

.NET = int

C++ = typedef signed int LONG32;

LONG64

.NET = long

C++ = typedef __int64 LONG64;

LPARAM

.NET = IntPtr

C++ = typedef LONG_PTR LPARAM;

LPBOOL

Bool *

.NET = IntPtr or bool

C++ = typedef BOOL *LPBOOL;

LPBYTE

Byte *

.NET = IntPtr or byte

C++ = typedef BYTE *LPBYTE;

LPCOLORREF

.NET = IntPtr or uint

C++ = typedef DWORD *LPCOLORREF;

LPCSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef CONST CHAR *LPCSTR;

LPCTSTR

.NET = string or IntPtr or StringBuilder

#ifdef UNICODE

C++ = typedef LPCWSTR LPCTSTR;

#else

C++ = typedef LPCSTR LPCTSTR;

LPCVOID

.NET = IntPtr

C++ = typedef CONST void *LPCVOID;

LPCWSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef CONST WCHAR *LPCWSTR;

LPDWORD

.NET = IntPtr or uint

C++ = typedef DWORD *LPDWORD;

LPHANDLE

.NET = IntPtr

C++ = typedef HANDLE *LPHANDLE;

LPINT

.NET = IntPtr or int

C++ = typedef int *LPINT;

LPLONG

.NET = IntPtr or int

C++ = typedef long *LPLONG;

LPSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef CHAR *LPSTR;

LPTSTR

.NET = string or IntPtr or StringBuilder

#ifdef UNICODE

C++ = typedef LPWSTR LPTSTR;

#else

C++ = typedef LPSTR LPTSTR;

LPVOID

.NET = IntPtr

C++ = typedef void *LPVOID;

LPWORD

.NET = IntPtr or ushort

C++ = typedef WORD *LPWORD;

LPWSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef WCHAR *LPWSTR;

LRESULT

.NET = IntPtr or int

C++ = typedef LONG_PTR LRESULT;

PBOOL

.NET = IntPtr or bool

C++ = typedef BOOL *PBOOL;

PBOOLEAN

.NET = IntPtr or bool

C++ = typedef BOOLEAN *PBOOLEAN;

PBYTE

.NET = IntPtr or byte

C++ = typedef BYTE *PBYTE;

PCHAR

.NET = IntPtr or char

C++ = typedef CHAR *PCHAR;

PCSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef CONST CHAR *PCSTR;

PCTSTR

.NET = string or IntPtr or StringBuilder

#ifdef UNICODE

C++ = typedef LPCWSTR PCTSTR;

#else

C++ = typedef LPCSTR PCTSTR;

PCWSTR

.NET = string or IntPtr or StringBuilder

C++ = typedef CONST WCHAR *PCWSTR;

PDWORD

.NET = IntPtr or uint

C++ = typedef DWORD *PDWORD;

PDWORDLONG

.NET = IntPtr or ulong

C++ = typedef DWORDLONG *PDWORDLONG;

PDWORD_PTR

.NET = IntPtr or uint

C++ = typedef DWORD_PTR *PDWORD_PTR;

PDWORD32

.NET = IntPtr or uint

C++ = typedef DWORD32 *PDWORD32;

PDWORD64

.NET = IntPtr or ulong

C++ = typedef DWORD64 *PDWORD64;

PFLOAT

.NET = IntPtr or single

C++ = typedef FLOAT *PFLOAT;

PHANDLE

.NET = IntPtr

C++ = typedef HANDLE *PHANDLE;

PHKEY

.NET = IntPtr

C++ = typedef HKEY *PHKEY;

PINT

.NET = IntPtr or int

C++ = typedef int *PINT;

PINT_PTR

.NET = IntPtr

C++ = typedef INT_PTR *PINT_PTR;

PINT32

.NET = IntPtr or int

C++ = typedef INT32 *PINT32;

PINT64

.NET = IntPtr or long

C++ = typedef INT64 *PINT64;

PLCID

.NET = IntPtr or uint

C++ = typedef PDWORD PLCID;

PLONG

.NET = IntPtr or int

C++ = typedef LONG *PLONG;

PLONGLONG

.NET = IntPtr or long

C++ = typedef LONGLONG *PLONGLONG;

PLONG_PTR

.NET = IntPtr or int

C++ = typedef LONG_PTR *PLONG_PTR;

PLONG32

.NET = IntPtr or int

C++ = typedef LONG32 *PLONG32;

PLONG64

.NET = IntPtr or long

C++ = typedef LONG64 *PLONG64;

POINTER_32

.NET = IntPtr or int

#if defined(_WIN64)

#define POINTER_32 __ptr32

#else

#define POINTER32

POINTER_64

.NET = IntPtr or long

#define POINTER_64 __ptr64

PSHORT

.NET = IntPtr or short

C++ = typedef SHORT *PSHORT;

PSIZE_T

.NET = IntPtr

C++ = typedef SIZE_T *PSIZE_T;

PSSIZE_T

.NET = IntPtr

C++ = typedef SSIZE_T *PSSIZE_T;

PSTR

.NET = IntPtr or string or StringBuilder

C++ = typedef CHAR *PSTR;

PTBYTE

.NET = IntPtr or char

C++ = typedef TBYTE *PTBYTE;

PTCHAR

.NET = IntPtr or string or StringBuilder

C++ = typedef TCHAR *PTCHAR;

PTSTR

.NET = IntPtr or string or StringBuilder

#ifdef UNICODE

C++ = typedef LPWSTR PTSTR;

#else

C++ = typedef LPSTR PTSTR;

PUCHAR

.NET = IntPtr or string or StringBuilder

C++ = typedef UCHAR *PUCHAR;

PUINT

.NET = IntPtr or uint

C++ = typedef UINT *PUINT;

PUINT_PTR

.NET = IntPtr or uint

C++ = typedef UINT_PTR *PUINT_PTR;

PUINT32

.NET = IntPtr or uint

C++ = typedef UINT32 *PUINT32;

PUINT64

.NET = IntPtr or ulong

C++ = typedef UINT64 *PUINT64;

PULONG

.NET = IntPtr or uint

C++ = typedef ULONG *PULONG;

PULONGLONG

.NET = IntPtr or ulong

C++ = typedef ULONGLONG *PULONGLONG;

PULONG_PTR

.NET = IntPtr or uint:

C++ = typedef ULONG_PTR *PULONG_PTR;

PULONG32

.NET = IntPtr or uint

C++ = typedef ULONG32 *PULONG32;

PULONG64

.NET = IntPtr or ulong

C++ = typedef ULONG64 *PULONG64;

PUSHORT

.NET = IntPtr or ushort

C++ = typedef USHORT *PUSHORT;

PVOID

.NET = IntPtr

C++ = typedef void *PVOID;

PWCHAR

.NET = IntPtr or string:

C++ = typedef WCHAR *PWCHAR;

PWORD

.NET = IntPtr or ushort

C++ = typedef WORD *PWORD;

PWSTR

.NET = IntPtr or string or StringBuilder

C++ = typedef WCHAR *PWSTR;

SC_HANDLE

.NET = IntPtr

C++ = typedef HANDLE SC_HANDLE;

SC_LOCK

.NET = IntPtr

C++ = typedef LPVOID SC_LOCK;

SERVICE_STATUS_HANDLE

.NET = IntPtr

C++ = typedef HANDLE SERVICE_STATUS_HANDLE;

SHORT

.NET = short

C++ = typedef short SHORT;

SIZE_T

.NET = uint or IntPtr

C++ = typedef ULONG_PTR SIZE_T;

SSIZE_T

.NET = int or IntPtr

C++ = typedef LONG_PTR SSIZE_T;

TBYTE

.NET = char

#ifdef UNICODE

C++ = typedef WCHAR TBYTE;

#else

C++ = typedef unsigned char TBYTE;

TCHAR

.NET = char

#ifdef UNICODE

C++ = typedef WCHAR TCHAR;

#else

C++ = typedef char TCHAR;

UCHAR

.NET = char

C++ = typedef unsigned char UCHAR;

UINT

.NET = uint:

C++ = typedef unsigned int UINT;

UINT_PTR

.NET = UIntPtr or uint:

#if defined(_WIN64)

C++ = typedef unsigned __int64 UINT_PTR;

#else

C++ = typedef unsigned int UINT_PTR;

UINT32

.NET = uint

C++ = typedef unsigned int

UINT32;

UINT64

.NET = ulong

C++ = typedef usigned __int

64 UINT64;

ULONG

.NET = uint:

C++ = typedef unsigned long ULONG;

ULONGLONG

.NET = ulong:

#if !defined(_M_IX86)

C++ = typedef unsigned __int64ULONGLONG;

#else

C++ = typedef double ULONGLONG

ULONG_PTR

.NET = IntPtr or uint

#if defined(_WIN64)

C++ = typedef unsigned __int64ULONG_PTR;

#else

C++ = typedef unsigned long ULONG_PTR;

ULONG32

.NET = uint

C++ = typedef unsigned int ULONG32;

ULONG64

.NET = ulong

C++ = typedef unsigned __int64 ULONG64;

USHORT

.NET = ushort

C++ = typedef unsigned short USHORT;

USN

.NET = long

C++ = typedef LONGLONG USN;

VOID

.NET = void:

#define VOID void

WCHAR

.NET = char

C++ = typedef wchar_t WCHAR;

WINAPI

.NET = standard is default, look at theCallingConvention enumeration:

#define WINAPI __stdcall

WORD

.NET = ushort

C++ = typedef unsigned short WORD;

WPARAM

.NET = IntPtr or uint:

C++ = typedef UINT_PTR WPARAM;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值