The way you described is the clearest way of doing this, presuming that you must deal with the struct
s in this manner. For completeness' sake, here's that method (with the implementation details of the packing omitted):
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
However, because you must know the exact offsets of each of the elements, you could also use this information to write directly to that field. F# does not provide a way of doing this using named identifiers, and its strict typing of the nativeptr<'T>
type means that you cannot simply cast to the relevant pointer type. The NativePtr.set offset ptr
function adds sizeof<'T> * offset
, so this is also no use in this case.
Let's say the type myStructure
has the Packed
attribute, for simplicity. The offsets are then 0 for a
, and 4 for b
. Throwing all caution to the wind, and completely abandoning the realm of managed memory, we could do:
let changeB pointer newB =
let bPtr =
NativePtr.toNativeInt pointer
|> (+) 4n
|> NativePtr.ofNativeInt<byte>
NativePtr.write bPtr newB
or even:
let changeMember pointer offset (value : 'T) =
let pointer' =
NativePtr.toNativeInt pointer
|> (+) (nativeint offset)
|> NativePtr.ofNativeInt<'T>
NativePtr.write pointer' value
I leave it an open question as to what the best method of dealing with these situations is, if they must be dealt with at all. I am inclined to go with the first, clearest method at the expense of additional memory use. The last, arbitrary offset method is to be avoided at all costs - if you must deal with adding raw offsets, it is much much better to wrap them in a more easily verifiable function like the second method, so the caller need not calculate the offset itself.
NativePtr<some struct>
and you want to set the named elements of thisstruct
? Do you have an example of how you are currently usingNativePtr.write
to achieve this in F#? – HippieNativePtr.write ptr p
. Prior to callingNativePtr.write
, I have updated a member within thep
struct. – Saltworks