我有一个winapi代码示例:
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 );
我想从.net拨打同一个电话,我写了这样的包装:
[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")
});
但是这段代码不起作用。我在哪里弄错了?
答案 0 :(得分:3)
可以肯定的是,尝试在C / C ++中调用printf(“%d \ n”,sizeof(CommunicationInfo))来了解实际大小。如果在32位系统上为(4 + 4 + 4),那么C#结构也必须是12字节大小。
“char *”指针也必须是指向非托管内存的指针,因此StringBuilder不会这样做。
有关编组示例
,请参阅此PInvoke error when marshalling struct with a string in it答案 1 :(得分:1)
正如Viktor所指出的,C / C ++ long
的大小为32位,因此需要与C#int
匹配。最重要的是,没有正确处理结构的传递。此外,由于您从未致电StringToHGlobalUni
,因此对FreeHGlobal
的呼叫会泄漏。
我可能会处理这样的编组:
[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);