gpt4 book ai didi

f# - F# 中具有零复制语义的不安全强制转换

转载 作者:行者123 更新时间:2023-12-04 21:11:26 34 4
gpt4 key购买 nike

我正在尝试实现像强制一样的静态转换,不会导致任何数据的复制。
天真的静态转换不起作用

let pkt = byte_buffer :> PktHeader

FS0193: Type constraint mismatch. The type byte[] is not compatible with type PktHeader The type 'byte[]' is not compatible with the type 'PktHeader' (FS0193) (program)



由于 System.Net.Sockets.Socket.Receive() 的定义方式,数据包最初保存在字节数组中。
低级数据包结构定义如下
[<Struct; StructLayout(LayoutKind.Explicit)>]
type PktHeader =
[<FieldOffset(0)>] val mutable field1: uint16
[<FieldOffset(2)>] val mutable field2: uint16
[<FieldOffset(4)>] val mutable field3: uint32
.... many more fields follow ....

在这个现实世界的场景中,效率很重要,因为浪费的数据复制可能会排除 F# 作为实现语言的可能性。
在这种情况下,您如何实现零复制效率?

11 月 29 日编辑
我的问题是基于隐含的信念,即 C/C++/C# 风格的不安全静态转换是一个有用的构造,就好像这是不言而喻的。然而,另一方面,这种类型转换在 F# 中并不惯用,因为它本质上是一种充满危险的命令式语言技术。出于这个原因,我接受了 V.B.其中 SBE/FlatBuffers 数据访问被公布为最佳实践。

最佳答案

用于转换的纯 F# 方法

let convertByteArrayToStruct<'a when 'a : struct> (byteArr : byte[]) = 
let handle = GCHandle.Alloc(byteArr, GCHandleType.Pinned)
let structure = Marshal.PtrToStructure (handle.AddrOfPinnedObject(), typeof<'a>)
handle.Free()
structure :?> 'a

这是一个最小的例子,但我建议对字节数组的长度进行一些检查,因为当它写在那里时,如果你给它一个太短的字节数组,它将产生未定义的结果。您可以查看 Marshall.SizeOf(typeof<'a>) .

没有比这更安全的纯 F# 解决方案(这已经是一种容易出现运行时故障的方法)。替代选项可能包括与 C# 的互操作以使用 unsafefixed进行转换。

但最终,您需要一种颠覆 F# 类型系统的方法,这并不是该语言的真正设计目标。 F# 的主要优势之一是类型系统的强大功能,它能够帮助您生成可静态验证的代码。

关于f# - F# 中具有零复制语义的不安全强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33940568/

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