F#Marshal.SizeOf异常涉及结构中的枚举数组

bug*_*der 6 enums f# struct sizeof marshalling

我遇到了涉及Marshal.SizeOf我不理解的运行时异常.在删除了大量代码之后,我想出了一个演示该问题的小例子:

#nowarn "9"

open System.Runtime.InteropServices

type Gray = | Black = 0 | Gray = 1 | White = 2

[<Struct; StructLayout(LayoutKind.Sequential, Pack = 1)>]
type GrayStruct =
    [<MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)>]
    val mutable Triple: Gray[]

type Color = | Red = 0 | Green = 1 | Blue = 2

[<Struct; StructLayout(LayoutKind.Sequential, Pack = 1)>]
type ColorStruct =
    [<MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)>]
    val mutable Triple: Color[]

let colorStructToUnit (colorStruct: ColorStruct) = ()

printfn "%A" (Marshal.SizeOf(typeof<GrayStruct>))
printfn "%A" (Marshal.SizeOf(typeof<ColorStruct>))
Run Code Online (Sandbox Code Playgroud)

使用fsi.exe(版本4.1)运行此示例会导致:

12
System.ArgumentException: Type 'FSI_0001+ColorStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
   at System.Runtime.InteropServices.Marshal.SizeOfHelper(Type t, Boolean throwIfNotMarshalable)
   at System.Runtime.InteropServices.Marshal.SizeOf(Type t)
   at <StartupCode$FSI_0001>.$FSI_0001.main@() in 
C:\f#\Example\example.fsx:line 21
Stopped due to error
Run Code Online (Sandbox Code Playgroud)

注意之间的相似GrayStructColorStruct,但Marshal.SizeOf扼流圈ColorStruct.Marshal.SizeOf似乎因为colorStructToUnit函数的存在而抛出异常.如果删除该功能,输出将变为:

12
12
Run Code Online (Sandbox Code Playgroud)

另外,如果我保留该colorStructToUnit功能,但替换:

    val mutable Triple: Color[]
Run Code Online (Sandbox Code Playgroud)

有:

    val mutable Triple: int[]
Run Code Online (Sandbox Code Playgroud)

然后输出也变成:

12
12
Run Code Online (Sandbox Code Playgroud)

感谢您对此问题的任何见解.


请注意,我在更大的代码库中遇到此问题,该代码库尝试通过PInvoke与旧DLL进行交互.此问题似乎只影响结构中的枚举数组.一种解决方法是封装底层类型(即int[]代替Color[]),然后将这些值转换为枚举,但该解决方案需要对几乎相同结构的多个定义.是否有更优雅的方法来克服这个问题?