Monday, April 6, 2009

Managed type signatures for P/Invoke Interop

Ran across an incredibly useful tool for native Interop. The P/Invoke Interop Assistant automagically generates managed signatures for calls to DLLs.

It can even take C/C++ declarations as input and generate the corresponding managed signature. The closest thing to this that I've seen before was the VB6 API text viewer but it had no ability to parse native code declarations.

After downloading it I used a call to RasDialDlg() (declared in RasDlg.h, implemented in RasDlg.dll) to test it out. The C++ declarations had to be modified a little, mainly to remove usage of #define, for correct parsing. Given the following input:
struct RASDIALDLG{ IN DWORD
dwSize; IN HWND hwndOwner; DWORD
dwFlags; LONG xDlg; LONG
yDlg; DWORD dwSubEntry; DWORD
dwError; ULONG_PTR reserved; ULONG_PTR
reserved2;};
BOOL APIENTRY RasDialDlgW( LPWSTR
lpszPhonebook, LPWSTR lpszEntry, LPWSTR lpszPhoneNumber,
RASDIALDLG *lpInfo )

The P/Invoke Interop Assistant produced the following managed signatures (inside a neat little wrapper class no less!):

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public
struct RASDIALDLG {
/// DWORD->unsigned int
public uint dwSize;
///
HWND->HWND__*
public System.IntPtr hwndOwner;
/// DWORD->unsigned
int
public uint dwFlags;
/// LONG->int
public int xDlg;
///
LONG->int
public int yDlg;
/// DWORD->unsigned int
public uint
dwSubEntry;
/// DWORD->unsigned int
public uint dwError;
///
ULONG_PTR->unsigned int
public uint reserved;
///
ULONG_PTR->unsigned int
public uint
reserved2;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public
struct HWND__ {
/// int
public int unused;
}
public partial class
NativeMethods {
/// Return Type: BOOL->int
///lpszPhonebook:
LPWSTR->WCHAR*
///lpszEntry: LPWSTR->WCHAR*
///lpszPhoneNumber:
LPWSTR->WCHAR*
///lpInfo:
RASDIALDLG*
[System.Runtime.InteropServices.DllImportAttribute("",
EntryPoint="RasDialDlgW")]
[return:
System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public
static extern bool
RasDialDlgW([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszPhonebook,
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszEntry,
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
System.Text.StringBuilder lpszPhoneNumber, ref RASDIALDLG lpInfo) ;
}

I really wish I had this tool a few months back when doing major interop. Ah well, better late than never.

No comments :

Post a Comment