Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在c中封送打包结构的非托管缓冲区#_C#_Arrays_Struct_Marshalling_Buffer - Fatal编程技术网

C# 如何在c中封送打包结构的非托管缓冲区#

C# 如何在c中封送打包结构的非托管缓冲区#,c#,arrays,struct,marshalling,buffer,C#,Arrays,Struct,Marshalling,Buffer,我正在(成功)使用以下pinvoke签名在c#中调用Windows FilterSendMessage函数: [DllImport("fltlib.dll")] public static extern IntPtr FilterSendMessage( IntPtr hPort, IntPtr inBuffer, UInt32 inBufferSize, IntPtr outBuffer, UInt32 o

我正在(成功)使用以下pinvoke签名在c#中调用Windows FilterSendMessage函数:

[DllImport("fltlib.dll")]
    public static extern IntPtr FilterSendMessage(
        IntPtr hPort,
        IntPtr inBuffer,
        UInt32 inBufferSize,
        IntPtr outBuffer,
        UInt32 outBufferSize,
        out UInt32 bytesReturned);
exputffer参数由任意数量的结构(一个接一个地打包)填充,在C中定义为:

typedef struct _BAH_RECORD {

    int evt
    int len;
    WCHAR name[1];

} BAH_RECORD, *PBAH_RECORD;
名称字段分配了一个长度可变、以null结尾的unicode字符串。len字段描述结构的总大小(以字节为单位)(包括名称字符串)。我相信在非托管端处理结构的方式没有问题

我的问题出现在我尝试将突发事件封送到BAH#U记录结构的实例时,该结构在c#中定义为:

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
公共结构BAH_记录
{
公共UInt32 evt;
公共UInt32 len;
公共字符串名称;
}
IntPtr EXBUFFER=Marshal.AllocHGlobal(输出缓冲区大小);
hResult=Win32.FilterSendMessage(返回HPORHandle、inBuffer、IN_BUFFER_大小、Exputffer、OUT_BUFFER_大小、OUT Bytes);
BAH_记录BAH=(BAH_记录)Marshal.ptr结构(突发,类型(BAH_记录));
如果我尝试打印/查看/显示bah.name,我会收到垃圾

为了确认Exputfer确实包含有效数据,我在c#中进行了一些粗略的指针黑客操作,对它进行了一步测试,调用Marshal.ReadInt32两次(覆盖前两个结构字段),然后多次调用Marshal.ReadByte来填充一个byte[],然后将其用作Encoding.Unicode.GetString()的参数……字符串很好,所以它肯定就在那里,我似乎无法让元帅正确地处理它(如果它可以的话?)

谢谢你的帮助


Steve

问题在于,C#BAH#u记录结构中的“name”字符串被封送为指向字符串(WCHAR*)的指针,但在C端它是一个内联WCHAR缓冲区。因此,当您封送结构时,运行时将读取缓冲区的前四个字节作为指针,然后尝试读取它指向的字符串

不幸的是,运行时无法自动封送结构中可变大小的缓冲区,因此您需要使用手动封送(或如您所说的“指针黑客”)。但是,当指针指向缓冲区时,不需要单独读取字节,然后将它们转换为字符串,只需调用Marshal.PtrToStringUni即可

[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>