序列化未知数组大小

9

您有一个接受字节数组的结构

byte[]

然而,该数组的大小取决于您提交的图像(宽度x高度)

那么...你该怎么做呢?

[MarshalAs(UnmanagedType.ByValArray, SizeConst = ???)]
public Byte[] ImageData;

在使用从C#传递到C DLL的字节数组时,sizeconst是否是必需的?


自定义编组程序似乎是唯一的选择。 - IS4
1个回答

3
你需要更改编组类型。如果你正在使用ByValArray进行编组,则需要SizeConst,但是其他类型不需要。有关详细信息,请查看UnmanagedType枚举
我怀疑你想要将其编组为指向C数组的指针:
[MarshalAs(UnmanagedType.LPArray)]

这将导致它通过标准C数组(BYTE*)进行编组,因此只传递指针。 这样做可以让您传递任何大小的数组。 通常,您还需要将数组大小作为另一个参数传递(或图像宽度/高度/bpp,提供相同的信息),因为在C/C++中很难轻松地告诉它。

感谢您的回复,Reed。然而,我已经这样做了,现在出现了以下错误:Invalid managed/unmanaged type combination (Arrays fields must be paired with ByValArray or SafeArray)当构建IntPtr并使用Marshal.StructureToPtr时...您有什么想法吗? - Olewolfe
看一下枚举。需要更多信息。我假设你是从托管->非托管进行编组,但如果你是反过来的,你可以将其作为IntPtr(而不是byte [])进行编组,或者设置它使用SafeArray。 - Reed Copsey
1
不幸的是,除了使用[MarshalAs(UnmanagedType.ArrayByVal, sizeConst = xxxx)]之外的任何东西都会搞乱内存寻址。因此,有一个包含byte[]的结构体需要转换为IntPtr,以便可以将其传递给DLL。而且byte[]中的数据被搞乱了。通过将数据从IntPtr复制到byte[]并查看数据来验证这一点,发现除非在结构体中设置了MarshalAs,否则所有内容都已更改。 - Olewolfe
1
@Olewolfe 我也遇到了同样的问题,使用PInvoke从托管代码调用非托管代码时,我的双精度数组也在结构体中。根据MSDN的说明,基元类型的一维数组本身是可平坦化的,但是包含可变基元类型数组的类型本身不是可平坦化的。我认为这意味着你的字节数组本身被认为是可平坦化的,但是一旦你将数组放入结构体中,结构体就失去了可平坦性。 - Ben
根据这篇文章所述,解决这个问题的方法是使用SAFEARRAY。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接