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 に答える