Click here to Skip to main content
15,861,168 members
Articles / Mobile Apps
Article

Win32 API: C++ to .NET

Rate me:
Please Sign up or sign in to vote.
3.77/5 (40 votes)
8 Mar 200512 min read 390.9K   112   88
This is a conversion sheet to go from C++ API calls to .NET P/Invoke. It includes data type conversions and tips.

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.

.NET API declaration form

VB.NET

VB
Declare Function <Name> Lib <dll name> <Optional fields> (<params>) _
                                                      As <return type>

C# definition

C#
[DllImport("<dll name>", <optional fields>)] 
        static extern <return type> <Method name> (<Params>)

Managed C++ .NET

MC++
[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

VB
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

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)

Managed C++. NET

MC++
[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.
  2. Some types like UIntPtr are not CLS compliant so I use IntPtr instead, but you can use any of these.
  3. The first choice that comes up after the "=" in the IDE’s Intellisense is the best choice usually.
  4. When using strings in COM Interop, for inputs you always use string for WCHAR*, TCHAR*, etc. For outputs you can use string or StringBuilder, but sometimes you need to use an IntPtr and marshal the characters out of it using Marshal.PtrToStructure() and increment the pointer till you get null characters. To increment a pointer turn it into an int and 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 other IntPtr 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 say ref <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 __int64 ULONGLONG;

#else

C++ = typedef double ULONGLONG

ULONG_PTR

.NET = IntPtr or uint

#if defined(_WIN64)

C++ = typedef unsigned __int64 ULONG_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 the CallingConvention enumeration:

#define WINAPI __stdcall

WORD

.NET = ushort

C++ = typedef unsigned short WORD;

WPARAM

.NET = IntPtr or uint:

C++ = typedef UINT_PTR WPARAM;

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionAbout C++ DLL used in VB.NET Pin
mehdishahgholi19-Oct-14 22:22
mehdishahgholi19-Oct-14 22:22 
QuestionNice Pin
Wisen Technologies17-Aug-13 2:44
Wisen Technologies17-Aug-13 2:44 
GeneralMy vote of 5 Pin
winxpdll14-Sep-11 4:33
winxpdll14-Sep-11 4:33 
Question80 bit floating point data type (long double) Pin
shazzard26-Aug-11 1:45
shazzard26-Aug-11 1:45 
AnswerRe: 80 bit floating point data type (long double) Pin
Herbert Lausmann3-Jan-14 5:39
professionalHerbert Lausmann3-Jan-14 5:39 
GeneralMarshal.GetDelegateForFunctionPointer alternate in C# Compact Framework Pin
Shatyamm Kumar10-Jun-10 16:26
Shatyamm Kumar10-Jun-10 16:26 
Generalplase Help Vc++DLL with VB.net Pin
yang sung yeol2-Jan-10 18:19
yang sung yeol2-Jan-10 18:19 
GeneralThanks! Pin
di~v~inci21-Dec-09 1:54
di~v~inci21-Dec-09 1:54 
Questionhelp Pin
almohandis3-Aug-08 9:50
almohandis3-Aug-08 9:50 
GeneralprinterAPI for c#.net Pin
balu1234530-Jul-08 7:49
balu1234530-Jul-08 7:49 
QuestionAPI call to get FAT32 partition Pin
irishrose031228-Nov-07 5:36
irishrose031228-Nov-07 5:36 
Questionp/invoke Pin
AGraca13-Nov-07 5:43
AGraca13-Nov-07 5:43 
AnswerRe: p/invoke Pin
kbrryder13-Nov-07 18:44
kbrryder13-Nov-07 18:44 
AnswerRe: p/invoke Pin
AGraca13-Nov-07 23:13
AGraca13-Nov-07 23:13 
GeneralRe: p/invoke Pin
kbrryder14-Nov-07 5:11
kbrryder14-Nov-07 5:11 
Generalintegrate a struct Pin
dark80m25-Sep-07 3:17
dark80m25-Sep-07 3:17 
QuestionHow To convert typedef char CONFIG_CTRL[585] in vb.net? Pin
spierre9-Dec-06 12:00
spierre9-Dec-06 12:00 
AnswerRe: How To convert typedef char CONFIG_CTRL[585] in vb.net? Pin
kbrryder9-Dec-06 13:06
kbrryder9-Dec-06 13:06 
You could try three things, try using a string as a parameter or try using a StringBuilder as a parameter or try using a byte array as a parameter. There are many different ways that might work.

-Kyle
Generaldisplay file icons in list view Pin
itbuff8-Nov-06 2:26
itbuff8-Nov-06 2:26 
GeneralQuestion about exposing HICON via COM C++ that .NET understands ... Pin
rjschweiger25-Oct-06 14:01
rjschweiger25-Oct-06 14:01 
GeneralRe: Question about exposing HICON via COM C++ that .NET understands ... Pin
rjschweiger25-Oct-06 14:18
rjschweiger25-Oct-06 14:18 
GeneralRe: Question about exposing HICON via COM C++ that .NET understands ... Pin
ranga@adobe1-Sep-07 7:48
ranga@adobe1-Sep-07 7:48 
GeneralGreat Pin
scanner7775-Jul-06 16:13
scanner7775-Jul-06 16:13 
QuestionHow to pass IntPtr to COM (Help, urgent) Pin
guocang5-Jul-06 11:05
guocang5-Jul-06 11:05 
AnswerRe: How to pass IntPtr to COM (Help, urgent) Pin
kbrryder5-Jul-06 11:33
kbrryder5-Jul-06 11:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.