2016-11-18 64 views
6

有什麼辦法可以訪問NativePtr結構體的成員併爲它們賦值,這與您在下面的示例中可以在C#中使用的方式大致相同?F#指針成員訪問器

(從MSDN)

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

目前我正在使用的NativePtr.write,但是我不能確定這是否是最好的/正確的解決方案。

謝謝。

+1

澄清 - 你有一個'NativePtr ',你想設置這個'struct'的命名元素?你有沒有一個例子說明你如何使用'NativePtr.write'在F#中實現這個功能? –

+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 

我離開它一個懸而未決的問題,以如果必須處理這些情況,那麼處理這些情況的方法是什麼。我傾向於以犧牲更多內存使用爲代價的第一個最清晰的方法。最後的任意偏移量方法是不惜一切代價來避免的 - 如果您必須處理添加原始偏移量,則將它們包裝在更容易驗證的函數(如第二個方法)中要好得多,因此調用者不需要計算偏移量本身。

+0

很好的答案,謝謝傑克。 –