I very excited to announce we recently released a tool I've been working on to MSDN that will greatly help with using PInvoke in managed code. The tool is called the "PInvoke Interop Assistant" and is included as part of a MSDN article on marshalling data for PInvoke and Reverse PInvoke scenarios.
Here is a link to the article and tool
The motivation behind this tool is writing PInvoke is a hard and often tedious task. There are many rules you must obey and many exceptions that must be taken into account. Anything beyond simple data structures gets very involved and subtle semantics of C can greatly change the needed signature. Incorrect translations often result in obscure exceptions or crashes.
In short, it's not any fun.
The tool works in several different ways to make PInvoke generation an easier process. The goal is to make generating managed code for structs, unions, enums, constants, functions, typedefs , etc ... as easy as possible. The resulting code can be generated in both VB and C#.
The GUI version of the tool operates in 3 modes.
The first two are the parts I worked on and represent the PInvoke scenarios. The third part was written by Ladi Prosek and will be covered in a different article. We chose the names SigImp and SigExp to mirror the tblimp/tlbexp tool base since they have similar functions.
Most adventures in PInvoke start with a developer having a small set of C code they would like to use from a managed binary. Typically it's one or two functions with several supporting C structs. Before, all of this would be hand translated into managed code from scratch. With this tool all you must do is paste the code into the tool and it will generate the interop signature for you.
For instance assume you wanted to translate the following C code into VB.
float CalculateData(S1* p);
Start up the tool and switch to the "SigImp Translate Snippet" tab. Then paste the code in and then hit the Generate button.
You can also set click the "Auto Generate" box and watch the code update as you type.
This translation is not limited to built-in C types. It will also resolve most commonly used windows types such as HANDLE, DWORD all the way up to complex structs such as WIN32_FIND_DATA
Often developers want to use C functions familiar to them in managed code. This can be a tedious task as well because if the signature is not already available you are back to coding from scratch. Even adding a constant value can be tricky if you don't know which header file to look in.
The tool also provides a database of many commonly used functions, structs, constants, etc ... It is essentially anything that is included from windows.h. Switch to the SigImp search tab, type the name of what you are looking for and hit generate. For example if I want to see the value for WM_PAINT just type it in.
In addition this part of the tool will also do dependency calculation. For instance if choose a method which has a parameter that is a C structure it will automatically generate the structure with the function. For instance if you choose the function FindFirstFile it will determine that the function depends on the WIN32_FIND_DATA structure. Furthermore it will notice that WIN32_FIND_DATA depends on FILETIME and generate both in addition to the method.
Public Structure WIN32_FIND_DATAW
Public dwFileAttributes As UInteger
Public ftCreationTime As FILETIME
Public ftLastAccessTime As FILETIME
Public ftLastWriteTime As FILETIME
Public nFileSizeHigh As UInteger
Public nFileSizeLow As UInteger
Public dwReserved0 As UInteger
Public dwReserved1 As UInteger
System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=260)> _
Public cFileName As String
System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=14)> _
Public cAlternateFileName As String
Public Structure FILETIME
Public dwLowDateTime As UInteger
Public dwHighDateTime As UInteger
Partial Public Class NativeMethods
'''Return Type: HANDLE->void*
<System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint:="FindFirstFileW")> _
Public Shared Function FindFirstFileW( _
ByVal lpFileName As String, _
ByRef lpFindFileData As WIN32_FIND_DATAW) As System.IntPtr
The snippet translator works well for small snippets of code. If you are trying to translate a much larger code base, say several interdependent header files the small snippet dialog won't work well. To work with larger code bases you should use the command line version of the tool; sigimp.exe. It is designed to process several header files and produce a mass output.
This tool started out as a pet project of mine some time ago. I'm extremely excited that customers are now going to be able to take advantage of it and I greatly look forward to any feedback you have. I will post a couple more articles in the future detailing how this tool works under the hood.