包含字节数组的编组结构

Posted

技术标签:

【中文标题】包含字节数组的编组结构【英文标题】:Marshalling structures containing byte array 【发布时间】:2014-10-03 08:14:02 【问题描述】:

第二天,我一直在努力解决如何将包含字节数组的结构传递给 c++ dll 的任务。即,我不知道如何编组 C# 结构。这是我的代码:

in C++ dll:

    struct Image
    
        int Width;
        int Height;
        int Depth;
        uchar *Data;
    ;
    .....
__declspec(dllexport) void DirectTransform(Image *InImage, Image*DestImage)  

...Implementation...

在 C# 程序中:

    [StructLayout(LayoutKind.Sequential)]
     struct ImageData
    
        public int Width;
        public int Height;
        public int Depth;
        [MarshalAs(UnmanagedType.LPArray)]
        public byte[] Data;
    
 [DllImport("MyDll.dll",CallingConvention=CallingConvention.Cdecl)]
        public static extern void DirectTransform(ImageData Src, ImageData Dest);

//Fill out both structures..

        DirectTransform(Image, DestImage);

调用 DirectTransform 时抛出异常并表示:

无法封送类型为“ImageData”的字段“数据”:托管/非托管无效 类型组合(数组字段必须与 ByValArray 或 安全阵列)。

当我将 LPArray 更改为 ByValArray 并指向数组的大小(在本例中为 202500)它也不起作用,因为大小太大。使用 SafeArray 时,程序在 DLL 中失败并显示以下消息:

试图读取或写入受保护的内存。这通常是一个 指示其他内存已损坏。 并且结构中的数据是错误的。

谁能帮帮我?

【问题讨论】:

必须是 IntPtr,用 Marshal.AllocHGlobal() 初始化。然而,Dest 参数是一个问题,您要么不知道要分配多大的数组,要么 C 代码分配了它,然后您就会发生内存泄漏。 【参考方案1】:

看看这个question

您可以尝试将指针传递给您的数组,例如整数长度字段。 这样做,您需要使用 Marshal.AllocHGlobal 手动分配非托管内存,调用您的函数,然后在 finally 块中 - 使用 Marshal.FreeHGlobal 自行清除

使用Marshal.Copy 方法,您可以将数据复制到分配的内存中。

【讨论】:

以上是关于包含字节数组的编组结构的主要内容,如果未能解决你的问题,请参考以下文章

解析的字节数组在解析成结构后变成垃圾

如何在 Parcel 的帮助下将 Parcelable 编组和解组为字节数组?

C# Struct 到字节数组的编组方式与 Delphi 中的打包记录相同

如何编组包含未知大小的 int 数组的结构?

将大端字节集合编组到结构中以提取值

导出的 C 函数与结构与 .Net 编组中的布尔大小