1

我有一个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")
    });

但是这段代码不起作用。我在哪里犯了错误?

4

2 回答 2

3

我相信,CommunicationInfo 结构中的“long”字段在 WinAPI 中是 32 位的。所以尝试在 C# 中将“internalMsg”定义为 System.Int32

可以肯定的是,尝试在 C/C++ 中调用 printf("%d\n", sizeof(CommunicationInfo)) 以了解实际大小。如果在 32 位系统上为 (4 + 4 + 4),则 C# 结构也必须为 12 字节大小。

“char*”指针也必须是指向非托管内存的指针,所以 StringBuilder 不会这样做。

为编组样本编组带有字符串的结构时,请参阅此PInvoke 错误

于 2012-05-20T21:55:30.350 回答
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);
于 2012-05-21T10:45:09.723 回答