我(成功地)使用以下的PInvoke签名调用C#中的视窗FilterSendMessage功能:

[DllImport("fltlib.dll")]
    public static extern IntPtr FilterSendMessage(
        IntPtr hPort,
        IntPtr inBuffer,
        UInt32 inBufferSize,
        IntPtr outBuffer,
        UInt32 outBufferSize,
        out UInt32 bytesReturned);

outBuffer 参数被填充有结构的(打包的一前一后)的任意数量的,在C定义为:

typedef struct _BAH_RECORD {

    int evt
    int len;
    WCHAR name[1];

} BAH_RECORD, *PBAH_RECORD;

名称字段被分配一个可变长度,空终止Unicode字符串。在 len个字段描述该结构的以字节为单位的总大小(包括名称字符串)。我相信没有什么错与如何结构在事情的非托管方进行处理。

我的问题出现了,当我尝试和封送outBuffer到BAH_RECORD结构的实例,在c#定义为:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct BAH_RECORD
{
    public UInt32 evt;
    public UInt32 len;
    public string name;
}

IntPtr outBuffer = Marshal.AllocHGlobal(OUT_BUFFER_SIZE);

hResult = Win32.FilterSendMessage(hPortHandle, inBuffer, IN_BUFFER_SIZE, outBuffer, OUT_BUFFER_SIZE, out bytesReturned);

BAH_RECORD bah = (BAH_RECORD)Marshal.PtrToStructure(outBuffer, typeof(BAH_RECORD));

<snip>

如果我试着和打印/查看/显示bah.name,我收到的垃圾......

要确认outBuffer实际上不包含有效数据,我做了一些粗指针两轮牛车在c#到步骤虽然它,调用Marshal.ReadInt32两次(以覆盖第一结构体2场),然后Marshal.ReadByte几次填充一个byte [],然后我作为一个参数Encoding.Unicode.GetString()使用...字符串出来罚款,所以它肯定在那里,我似乎无法得到编组正确处理它(如果它甚至可以吗?)

任何帮助理解

史蒂夫

有帮助吗?

解决方案

的问题是,在C#BAH_RECORD结构中的“名称”的字符串被编组作为一个指针到一个字符串(WCHAR *),但是,从C侧它是一个内联WCHAR缓冲器。所以,当你元帅你的结构运行时读取前四个字节的缓冲区指针,然后尝试读取该字符串,它指向。

不幸的是,没有办法运行时自动编组内结构可变大小的缓冲器,所以你将需要使用手动编组(或说“指针两轮牛车”)。但是,当你前进的指针在缓冲区指向你不需要在字节单独读取,然后将它们转换为字符串 - 只需拨打Marshal.PtrToStringUni

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top