Accessing Unmanaged Code from Managed Code
(or How to Call a C++ Function from C# and VB.NET)



See p. 237-239 in Programming Microsoft Windows with C#, by Charles Petzold.


Platform Invocation Services (PInvoke) mechanism for calling functions exported from DLLs. Can be used to call Win32 API functions or custom functions created in a language like C++.



Example C++ Function:


#define EXPORT extern "C" __declspec (dllexport)


EXPORT void MyDrawLine(HDC hdc, int x1, int y1, int x2, int y2,

COLORREF color, int width)


HPEN hPen = CreatePen(PS_SOLID, width, color);

HPEN hPenSave = (HPEN) SelectObject(hdc, hPen);


MoveToEx(hdc, x1, y1, NULL);

LineTo(hdc, x2, y2);


SelectObject(hdc, hPenSave);






Assume the code above was compiled into a DLL called graphiclib.dll. It could then be accessed like so:


C# Example Call:


using System.Runtime.InteropServices;


struct ColorRef


public byte red, green, blue;

private byte unused;


public ColorRef(byte r, byte g, byte b)


red = r;

green = g;

blue = b;

unused = 0;





private static extern void MyDrawLine(System.IntPtr hdc, int x1, int y1,

int x2, int y2, ColorRef color, int width);


Graphics g = CreateGraphics();

System.IntPtr hdc = g.GetHdc();
ColorRef red = new ColorRef(255, 0, 0);

MyDrawLine(hdc, 0, 0, 150, 200, red, 1);





VB.NET Example Call:


Imports System.Runtime.InteropServices


Structure ColorRef

Public red, green, blue As Byte

Private unused As Byte


Public Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte)

red = r

green = g

blue = b

unused = 0

End Sub

End Structure


Declare Auto Sub MyDrawLine Lib "GraphicLib.dll" (ByVal hdc As System.IntPtr, _

ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer, _

ByVal color As ColorRef, ByVal width As Integer)


Dim g As Graphics = Me.CreateGraphics()

Dim hdc As System.IntPtr = g.GetHdc()

Dim red As New ColorRef(255, 0, 0)

MyDrawLine(hdc, 0, 0, 150, 200, red, 1)