2016-11-18 5 views
6

構造体NativePtrのメンバにアクセスし、値を代入する方法はありますか?以下の例のC#の場合と同じですか? (MSDNから)F#ポインタメンバアクセッサ

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

現在、私はNativePtr.writeの使用を作ってるんだ、しかし私はこれが最善の/正解であるかどうかわかりませんよ。

ありがとうございました。

+1

明確にするために、 'NativePtr 'があり、この 'struct 'の名前付き要素を設定したいのですか? F#でこれを達成するために現在どのように 'NativePtr.write 'を使用しているかの例がありますか? –

+2

はい、正しいです。私は更新したい値を取る関数を作った.NativePtrとそのポインタからの逆参照された構造体は 'NativePtr.write ptr p'となる。 'NativePtr.write'を呼び出す前に、' p'構造体内のメンバを更新しました。 –

答えて

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 

のように私は、未解決の問題のままベストこれらの状況を処理する方法は、それらをまったく処理しなければならない場合です。私は追加のメモリ使用を犠牲にして、最初の、最も明白な方法に行く傾向があります。最後の任意のオフセットメソッドは、すべてのコストをかけて回避する必要があります。生のオフセットを追加する必要がある場合は、2番目のメソッドのようにより簡単に検証可能な関数にラップする方がずっと良いので、呼び出し元はオフセットを計算する必要はありません自体。

+0

すばらしい答え、Jakeに感謝します。 –