Is there any way of accessing the members of a NativePtr
struct and assigning a value to them, much in the same way that you can in C# in the below example?
(From MSDN)
CoOrds* p = &home;
p -> x = 25;
Currently I'm making use of NativePtr.write
, however I'm unsure whether this is the best/correct solution.
Thanks.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With