Click here to Skip to main content
Click here to Skip to main content

Win32 API: C++ to .NET

, 8 Mar 2005
Rate this:
Please Sign up or sign in to vote.
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

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.
  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

Share

About the Author

kbrryder

United States United States
No Biography provided

Comments and Discussions

 
QuestionAbout C++ DLL used in VB.NET [modified] Pinmembermehdishahgholi19-Oct-14 23:22 
QuestionNice PingroupWisen Technologies17-Aug-13 3:44 
GeneralMy vote of 5 Pinmemberwinxpdll14-Sep-11 5:33 
Question80 bit floating point data type (long double) Pinmembershazzard26-Aug-11 2:45 
AnswerRe: 80 bit floating point data type (long double) PinmemberHerbert Lausmann3-Jan-14 6:39 
Hello,
 
You might try System.Decimal (aka decimal in C#) - this is a 96-bit number, with base-10 arithmetic (rounding etc), making it particularly suitable for scenarios involving things like currency. It doesn't map to IEEE, but depending on the C compiler, neither does long double Poke tongue | ;-P Note that it is implemented in software.
 
From: Converting long double in .NET
GeneralMarshal.GetDelegateForFunctionPointer alternate in C# Compact Framework PinmemberSatyam Kumar10-Jun-10 17:26 
Generalplase Help Vc++DLL with VB.net Pinmemberyang sung yeol2-Jan-10 19:19 
GeneralThanks! Pinmemberdi~v~inci21-Dec-09 2:54 
Questionhelp Pinmemberalmohandis3-Aug-08 10:50 
GeneralprinterAPI for c#.net Pinmemberbalu1234530-Jul-08 8:49 
QuestionAPI call to get FAT32 partition Pinmemberirishrose031228-Nov-07 6:36 
Questionp/invoke PinmemberAGraca13-Nov-07 6:43 
AnswerRe: p/invoke Pinmemberkbrryder13-Nov-07 19:44 
AnswerRe: p/invoke PinmemberAGraca14-Nov-07 0:13 
GeneralRe: p/invoke Pinmemberkbrryder14-Nov-07 6:11 
Generalintegrate a struct Pinmemberdark80m25-Sep-07 4:17 
QuestionHow To convert typedef char CONFIG_CTRL[585] in vb.net? Pinmemberspierre9-Dec-06 13:00 
AnswerRe: How To convert typedef char CONFIG_CTRL[585] in vb.net? Pinmemberkbrryder9-Dec-06 14:06 
Generaldisplay file icons in list view Pinmemberitbuff8-Nov-06 3:26 
GeneralQuestion about exposing HICON via COM C++ that .NET understands ... Pinmemberrjschweiger25-Oct-06 15:01 
GeneralRe: Question about exposing HICON via COM C++ that .NET understands ... Pinmemberrjschweiger25-Oct-06 15:18 
GeneralRe: Question about exposing HICON via COM C++ that .NET understands ... Pinmemberranga@adobe1-Sep-07 8:48 
GeneralGreat Pinmemberscanner7775-Jul-06 17:13 
QuestionHow to pass IntPtr to COM (Help, urgent) Pinmemberguocang5-Jul-06 12:05 
AnswerRe: How to pass IntPtr to COM (Help, urgent) Pinmemberkbrryder5-Jul-06 12:33 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 8 Mar 2005
Article Copyright 2005 by kbrryder
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid