La façon dont vous avez décrit est la manière la plus claire de le faire, en supposant que vous devez traiter les struct
s de cette manière. Par souci de l'exhaustivité, voici cette méthode (avec les détails de mise en œuvre de l'emballage omis):
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
Cependant, parce que vous devez connaître les compensations exactes de chacun des éléments, vous pouvez également utiliser ces informations pour écrire directement à ce domaine. F # ne fournit pas un moyen de le faire en utilisant des identifiants nommés, et sa frappe stricte du type nativeptr<'T>
signifie que vous ne pouvez pas simplement convertir le type de pointeur approprié. La fonction NativePtr.set offset ptr
ajoute sizeof<'T> * offset
, ce qui est également inutile dans ce cas.
Supposons que le type myStructure
possède l'attribut Packed
, pour plus de simplicité. Les décalages sont alors 0 pour a
et 4 pour b
. Jeter toute la prudence au vent, et abandonner complètement le domaine de la mémoire gérée, nous pourrait faire:
let changeB pointer newB =
let bPtr =
NativePtr.toNativeInt pointer
|> (+) 4n
|> NativePtr.ofNativeInt<byte>
NativePtr.write bPtr newB
ou même:
let changeMember pointer offset (value : 'T) =
let pointer' =
NativePtr.toNativeInt pointer
|> (+) (nativeint offset)
|> NativePtr.ofNativeInt<'T>
NativePtr.write pointer' value
Je laisse une question ouverte à Quelle est la meilleure façon de traiter ces situations, si elles doivent être traitées du tout. Je suis enclin à aller avec la première méthode, la plus claire au détriment de l'utilisation de la mémoire supplémentaire. La dernière méthode de décalage arbitraire doit être évitée à tout prix - si vous devez ajouter des compensations brutes, il est beaucoup mieux de les enrouler dans une fonction plus facilement vérifiable comme la seconde méthode, donc l'appelant n'a pas besoin de calculer le décalage lui-même.
Pour clarifier - vous avez un 'NativePtr' et vous voulez définir les éléments nommés de cette 'struct'? Avez-vous un exemple de la façon dont vous utilisez actuellement 'NativePtr.write' pour réaliser ceci en F #? –
Oui c'est correct. J'ai fait une fonction qui prend la valeur que je souhaite mettre à jour, le NativePtr et la structure déréférencée de ce pointeur: 'NativePtr.write ptr p'. Avant d'appeler 'NativePtr.write', j'ai mis à jour un membre dans la structure' p'. –