gpt4 book ai didi

.net - 如何将 StructureToPtr 与 F# 结构一起使用?故障类型

转载 作者:行者123 更新时间:2023-12-05 02:24:55 27 4
gpt4 key购买 nike

我有结构:

type OneDevice = {
mutable id : System.UInt16
mutable typeDev : byte
mutable portNum : byte
mutable Parity : byte
mutable StopBits : byte
mutable BaudRate : byte
mutable addr1 : byte
mutable addr2 : byte
mutable useCanal : byte
mutable idGroup1 : byte
mutable idGroup2 : byte
mutable idGroup3 : byte
mutable idGroup4 : byte
mutable idGroupSos1 : byte
mutable idGroupSos2 : byte
mutable idGroupSos3 : byte
mutable idGroupSos4 : byte
mutable idSosReserv : byte
mutable addrModbus : byte
mutable offsetModbus : System.UInt16
mutable pwd : byte array
mutable offsetInModbus : System.UInt16
mutable reserv : System.UInt16
}

我需要复制一些用作字节数组。在 C# 中,我可以在这里声明字节数组的大小,但现在我不知道 pwd 的大小。

我正在尝试使用:

let memcp(device : OneDevice, bytes : byte array) =
Array.zeroCreate <| Marshal.SizeOf(typeof<OneDevice>)
|> fun (array : byte array) ->
GCHandle.Alloc(array, GCHandleType.Pinned) |> fun handle ->
Marshal.StructureToPtr(device, handle.AddrOfPinnedObject(), true)
handle.Free()

但是得到错误信息:

Error Unable to package type "Model + OneDevice" as an unmanaged structure; impossible to calculate the size or offset that make sense.

我想那是因为我不知道这里的密码大小。那么如何在 F# Structure 上使用它呢?或者也许我可以以某种方式声明静态大小的数组类型?

谢谢

最佳答案

您需要使用 StructLayout 属性确保您正在编码的结构与 native 结构具有相同的布局,例如。

[<type: StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)>]
type OneDevice = {
...

此外,如果需要使用非默认编码(marshal)处理行为(例如数组)进行编码(marshal)处理,则需要使用 MarshalAs 属性显式标记任何字段。数组的默认编码(marshal)处理行为是 LPArray,但听上去,您的 native 结构需要 ByValArray

[<field: MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)>]
mutable pwd : byte array

最后,将 GCHandle.Alloc 替换为 Marshal.AllocHGlobal 以分配非托管内存,并使用 Marshal.FreeHGlobal 释放它。

注意:我不确定 F# 记录类型是否可以接受这些属性,但我希望它们能够工作。如果没有,那么您需要将它们与 jpalmer 关于使用 struct 的建议结合使用。

编辑:

let size = Marshal.SizeOf(typeof<OneDevice>)
let unmanagedPtr = Marshal.AllocHGlobal(size)
Marshal.StructureToPtr(device, unmanagedPtr, false)
Marshal.Copy(unmanagedPtr, bytes, 0, size)
Marshal.FreeHGlobal(unmanagedPtr)

编辑:

以上内容用于将填充的 OneDevice 结构复制到空字节数组中。如果您想进行相反的操作 - 将填充的字节数组转换为结构,这在很大程度上是一样的。

let size = Marshal.SizeOf(typeof<OneDevice>)
let unmanagedPtr = Marshal.AllocHGlobal(size)
Marshal.Copy(bytes, unmanagedPtr, 0, size)
Marshal.PtrToStructure(unmanagedPtr, device)
Marshal.FreeHGlobal(unmanagedPtr)

关于.net - 如何将 StructureToPtr 与 F# 结构一起使用?故障类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7267542/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com