A blog by Devendra Tewari
This blog post tries to capture some essential points to remember when using p/invoke from C#.
You can expose static methods of a C++ class using the __declspec(dllexport) modifier. The C++ compiler adds each method to the exports table of a DLL with a different name. Use the dumpbin utility (distributed with Visual Studio) to get the exported name of a method and add an EntryPoint field to the DllImport
attribute. Dependency Walker is another good tool that shows the exports.
Essential P/Invoke has a table of type mappings and other tips regarding marshalling. In case you need to pass, or receive, an array of bytes—char*
in C or C++—or any opaque pointer, the [IntPtrhttps://docs.microsoft.com/en-us/dotnet/api/system.intptr) structure can be used. Use the Copy method from the System.Runtime.InteropServices.Marshal class to recover data as an array of bytes.
Calling Conventions Demystified describes the different calling conventions in great detail. If you haven’t specified conventions in your Visual C++ code, either by using __stdcall
or __cdecl
, or by changing the compiler setting, you should remember to set the CallingConvention field in the DllImport
Attribute to CallingConvention.Cdecl
.
PInvoke-Reverse PInvoke and __stdcall – __cdecl demonstrates passing delegates. In particular, it shows the right calling convention for .NET delegates—__stdcall
. You can tell C# to use CallingConvention.Cdecl
using the UnmanagedFunctionPointer
attribute. You need to create a new instance of the delegate and pass that in your p/invoke call. Passing just the method name can lead to a hard to decipher System.AccessViolationException
.
SWIG can generate C# code that wraps any C/C++ header.
P/Invoke Interop Assistant automatically generates C# p/invoke declarations for type and function declarations in C and C++.
Redgate has a free plugin for Visual Studio that can help you to find and contribute p/invoke signatures for well known APIs.