分类: WINDOWS
2008-02-28 09:15:47
|
ArraySubType=UnmanagedType.I1,
顾名思义, Marshal时应该每个数组元素占用一个字节, 正好对应C++中的小写bool变量占用的存储空间, 实际情况是: 不管你指定I1, I2, I4, Bool这些合法取值中的任何一个, Marshal的真正行为都是把每个元素作占用4字节对待. 而普通的bool变量, 则可以根据指定的I1, I2 Marshal成指定的存储空间大小.UnmanagedType
的取值根据命令行参数而定, 第一个参数指定bool[]的ArraySubType,
第二个参数指定普通bool变量的UnmanagedType.
对于bool合法的取值有I1, I2, I4, Bool. 那么可能的参数组合有16种, 通过bash的命令行扩展机制可以巧妙地得到:
echo {{I1,I2,I4,Bool}-{I1,I2,I4,Bool}}
结果是
I1-I1 I1-I2 I1-I4 I1-Bool I2-I1 I2-I2 I2-I4 I2-Bool I4-I1 I4-I2 I4-I4 I4-Bool Bool-I1 Bool-I2 Bool-I4 Bool-Bool
用vim把上述结果稍加整理形成下面的批处理:
Marshal_Bool_UnmanagedType.exe Bool Bool
Marshal_Bool_UnmanagedType.exe Bool I1
Marshal_Bool_UnmanagedType.exe Bool I2
Marshal_Bool_UnmanagedType.exe Bool I4
Marshal_Bool_UnmanagedType.exe I1 Bool
Marshal_Bool_UnmanagedType.exe I1 I1
Marshal_Bool_UnmanagedType.exe I1 I2
Marshal_Bool_UnmanagedType.exe I1 I4
Marshal_Bool_UnmanagedType.exe I2 Bool
Marshal_Bool_UnmanagedType.exe I2 I1
Marshal_Bool_UnmanagedType.exe I2 I2
Marshal_Bool_UnmanagedType.exe I2 I4
Marshal_Bool_UnmanagedType.exe I4 Bool
Marshal_Bool_UnmanagedType.exe I4 I1
Marshal_Bool_UnmanagedType.exe I4 I2
Marshal_Bool_UnmanagedType.exe I4 I4
调用的结果是: 对于某些组合, 如I4, I4 程序会在调用 Marshal.SizeOf时抛出异常, 这说明此种结构定义无法进行正确的Marshal, 这样的结果无论怎样看都是一个bug, 把同一个结构中的bool数组和bool变量指定为相同的I4竟不允许, 下面是我对测试结果的简单统计: 16种组合中有8种是不允许的:
// arr var 1.1 2.0
// I2 I2 × ×
// I2 I4 × ×
// Bool I2 × ×
// Bool I4 × ×
// I1 I2 × ×
// I1 I4 × ×
// I4 I2 × ×
// I4 I4 × ×
我个人的理解, 没有理由不允许上述组合. 尤其是对于同构的I4 I4和I2 I2组合竟不允许, 而从占用空间的角度, Bool也是4个字节, 但Bool Bool的组合却是允许的, 再仔细看, 非法的组合还是非对称的, 比如Bool I2的组合非法, 但I2 Bool却合法, 总之, Marshal对于这种情况的处理给人的直观印象是完全丧失了理智.
异常信息如下:
System.ArgumentException: Type CodeDomWrapper.TestBool can not be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
at System.Runtime.InteropServices.Marshal.SizeOf(Type t)
at Slimzhao.Csharp.Test.Marshal_Ptr2Structure.Test.Main(String[] args)
再说一遍, .NET 2.0也
有同样的问题存在
|