F# 指针成员访问器

F# pointer member accessor

有没有什么方法可以访问 NativePtr 结构的成员并为它们赋值,就像在下面的示例中使用 C# 一样?

(来自 MSDN)

CoOrds* p = &home; p -> x = 25;

目前我正在使用 NativePtr.write,但是我不确定这是否是 best/correct 解决方案。

谢谢。

假设您必须以这种方式处理 struct,您描述的方式是最清晰的方式。为了完整起见,这是该方法(省略了打包的实现细节):

open FSharp.NativeInterop

[<StructLayout(...)>]
type myStructure =
    struct
        val mutable a : int
        val mutable b : byte
    end

let changeA pointer newA =
    let mutable structure = NativePtr.read pointer
    structure.a <- newA
    NativePtr.write pointer structure

但是,因为您必须知道每个元素的确切偏移量,所以您也可以使用此信息直接写入该字段。 F# 不提供使用命名标识符执行此操作的方法,并且其严格类型化的 nativeptr<'T> 类型意味着您不能简单地强制转换为相关的指针类型。 NativePtr.set offset ptr函数添加了sizeof<'T> * offset,所以这在本例中也是没有用的。

为简单起见,假设类型 myStructure 具有 Packed 属性。 a 的偏移量为 0,b 的偏移量为 4。抛开所有谨慎,完全放弃托管内存领域,我们可以做:

let changeB pointer newB =
    let bPtr =
        NativePtr.toNativeInt pointer
        |> (+) 4n
        |> NativePtr.ofNativeInt<byte>
    NativePtr.write bPtr newB

甚至:

let changeMember pointer offset (value : 'T) =
    let pointer' =
        NativePtr.toNativeInt pointer
        |> (+) (nativeint offset)
        |> NativePtr.ofNativeInt<'T>
    NativePtr.write pointer' value

我留下一个悬而未决的问题,即如果必须处理这些情况,最好的 方法是什么。我倾向于使用第一种最清晰的方法,但要以额外的内存使用为代价。最后,要不惜一切代价避免使用任意偏移方法——如果你必须处理添加原始偏移,最好将它们包装在一个更容易验证的函数中,如第二种方法,这样调用者就不需要计算偏移本身。