La bonne utilisation de UnsafePointer<> et UnsafeMutablePointer<>

Bonjours à  tous.


Je me demande depuis un moment comment UnsafePointer et UnsafeMutablePointer fonctionnent.


 


J'ai bien compris que c'était comme un pointeur en C avec une déclaration et une allocation.



var ptr = UnsafeMutablePointer<CGFloat>.alloc(4) 

Ensuite je rempli tout ça :



UIColor.cyanColor().getRed(ptr, green: ptr+1, blue: ptr+2, alpha: ptr+3)
ptr[0] // 0
ptr[1] // 1
ptr[2] // 1
ptr[3] // 1

Maintenant la question c'est de savoir comment je vais libérer cet espace mémoire. ptr est de type UnsafeMutablePointer, une structure qui sera gérée directement par Swift. Par contre la mémoire pointée c'est pour bibi et là  je ne sais pas:



ptr.dealloc(4)

suffit ? Ou alors



ptr.destroy(4)
ptr.dealloc(4)

est ce qu'il faut faire. Ou bien est-ce qu'on peut simplement faire:



ptr.destroy(4)

?


 


De la meme manière dans une fonction je récupère un UnsafeMutablePointer<Void> (le fameux void * très pratique en C) mais il faut que j'en ressorte une struct de type ShadingData:



let data = UnsafePointer<ShadingData>(info).memory

Est-ce que cette manière de faire est bonne ou est-ce que je dois faire autrement ?


 


La doc ne m'aide pas beaucoup dans ces cas là  mais vous je sais que vous vous pourrez ! 


 


Réponses

  • Ah bah visiblement je ne suis pas le seul à  ne pas savoir  :P


  • Pour ma part je fais comme tu l'as utilisé dans le premier message. Mais j'ai cru lire sur les forum d'apple ou autre part que c'était pas forcément obligatoire d'appeler dealloc et destroy. Tout dépend de comment tu l'as récupéré.


  • PyrohPyroh Membre
    avril 2016 modifié #5

    Merci pour vos réponses. Au final j'ai fait des tests et utilisé Instruments la bonne méthode quand on crée soit meÌ‚me un UnsafeMutablePointer<> est la suivante:



    // Création du pointeur
    let ptr = UnsafeMutablePointer<CGFloat>.alloc(1)
    // Initialisation du pointeur
    let value = CGFloat(42.0)
    ptr.initialize(value)

    // A partir de maintenant le retain count de value est de 2
    // Quand il sortira du scope il restera de 1 à  cause de ptr (ARC s'étant occupé de la variable locale)

    // Pour vraiment mettre le retain count de la structure pointée par ptr à  0 il faut faire dans l'ordre:
    ptr.destroy() // ou ptr.destroy(x) si on a alloué x espaces memoire.
    ptr.dealloc(1) // ptr.dealloc(x) si on a alloué x espaces memoire.

    Pour ptr c'est ARC qui s'occupera de release la structure (parce que les pointeurs sont des structures en Swift).


     


    À noter qu'il n'y a pas besoin de s'occuper du sort des UnsafePointer qui se demerdent tout seuls.


    Par contre j'ai du mal à  saisir si un UnsafePointer incrémente le retain count de la valeur pointée... Si non alors quelle est la raison d'exister de UsafeBufferPointer qui lui n'incrémente pas le retain count. Je vais investiguer.


  • AliGatorAliGator Membre, Modérateur
    Note que la création et l'utilisation de UnsafePointer et UnsafeMutablePointer directement par toi reste rare.

    En général soit on préfère utiliser la fonction "withUnsafePointer(...)" qui se charge de wrapper un T dans un UnsafePointer<T> et de gérer l'allocation et déallocation, soit on utilise directement l'opérateur "&" plutôt que s'embêter à  créer soi-même le UnsafeMutablePointer:


    var colors: [CGFloat] = [0,0,0,0]
    UIColor.cyanColor().getRed(&colors[0], green: &colors[1], blue: &colors[2], alpha: &colors[3])
    colors // [0, 1, 1, 1]
    NB : Bien sûr si la fonction attend un UnsafePointer<T> tu peux utiliser "let" pour déclarer la variable sur laquelle tu vas appliquer le "&", mais si la fonction attend un UnsafeMutablePointer<T> il faut que la variable soit déclarée "var" pour que le pointeur sous-jacent créé par "&" soit un UnsafeMutablePointer.
  • PyrohPyroh Membre

    Ah j'avais jamais pensé à  faire un &color. Merci du tuyau !


Connectez-vous ou Inscrivez-vous pour répondre.