Reputation: 3164
I have an example of winapi code:
struct CommunicationInfo {
long internalMsg;
const TCHAR * srcModuleName;
void * info;
};
...
const TCHAR* szText = _T("Hello from my plugin!\n(test message)");
CommunicationInfo ci = { 0x0401, cszMyPlugin, (void *) szText };
::SendMessage( hNppWnd, 0x111, (WPARAM) _T("NppExec.dll"), (LPARAM) &ci );
I want make the same call from .net and i wrote such wrapper:
[StructLayout(LayoutKind.Sequential)]
public struct CommunicationInfo
{
public Int64 internalMsg;
[MarshalAs(UnmanagedType.LPWStr)]
public StringBuilder srcModuleName;
[MarshalAs(UnmanagedType.LPWStr)]
public StringBuilder data;
};
...
[DllImport("user32")]
public static extern IntPtr SendMessage(IntPtr hWnd,
NppMsg Msg, IntPtr wParam,
[MarshalAs(UnmanagedType.Struct)] CommunicationInfo communicationInfo);
...
SendMessage(hNppWnd, 0x111,
Marshal.StringToHGlobalUni("NppExec.dll"),
new CommunicationInfo
{
data = new StringBuilder("test test"),
internalMsg = 0x0401,
srcModuleName = new StringBuilder("ModuleName")
});
But this code doesn't work. Where did I make a mistake ?
Upvotes: 1
Views: 1187
Reputation: 612963
As Viktor points out, C/C++ long
is 32 bits in size so needs to be matched with C# int
. On top of that, the passing of the struct is not handled correctly. In addition the call to StringToHGlobalUni
leaks since you never call FreeHGlobal
.
I'd probably handle the marshalling something like this:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CommunicationInfo
{
public int internalMsg;
public string srcModuleName;
public string data;
};
....
[DllImport("user32")]
public static extern IntPtr SendMessage(
IntPtr hWnd,
uint Msg,
[MarshalAs(UnmanagedType.LPWStr)] string wParam,
ref CommunicationInfo communicationInfo
);
....
CommunicationInfo communicationInfo = new CommunicationInfo
{
internalMsg = 0x0401,
srcModuleName = "ModuleName",
data = "test test"
};
SendMessage(hNppWnd, 0x111, "NppExec.dll", ref communicationInfo);
Upvotes: 1
Reputation: 14467
"long" field in CommunicationInfo struct is 32-bit in WinAPI, I believe. So try defining "internalMsg" as System.Int32 in C#
To be sure, try calling printf("%d\n", sizeof(CommunicationInfo)) in C/C++ to know the actual size. If it is (4 + 4 + 4) on a 32-bit system, then the C# struct must also be of 12 byte size.
The "char*" pointer must also be the pointer to unmanaged memory, so the StringBuilder just won't do.
See this PInvoke error when marshalling struct with a string in it for the marshalling sample
Upvotes: 3