F#指针成员访问器

时间:2016-11-18 20:33:34

标签: c# .net f# interop pinvoke

有没有办法访问NativePtr结构的成员并为它们赋值,这与下面示例中的C#相同?

(来自MSDN)

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

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

感谢。

1 个答案:

答案 0 :(得分:4)

您描述的方式是最明确的方式,假设您必须以这种方式处理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

对于处理这些情况的最佳方法,如果必须处理这些问题,我会留下一个悬而未决的问题。我倾向于采用第一种最清晰的方法,而不考虑额外的内存使用。不惜一切代价避免使用最后的任意偏移方法 - 如果必须处理添加原始偏移量,将它们包装在更易于验证的函数(如第二种方法)中要好得多,因此调用者无需计算偏移量本身。