如何封送在c#包装结构的非托管的缓冲区
-
21-08-2019 - |
题
我(成功地)使用以下的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
不隶属于 StackOverflow