SommaireTelecharger la documentationChapitre suivantChapitre precedent  

  .: News :.: Edito :.: Scripts :.: Forum :.: Erreurs :.: Jobs :. 
 
Sommaire

Créer des variables

Présentation
Longs (Entiers)
Doubles (nombres à virgule flottante)
Chaînes de caractères
Booléens
Tableaux
Objets
Ressources
Les macros de création automatiques de variables globales
Creating Constants

7.11.8 Ressources

Les resources représentent un type de données spécial en PHP. Le terme de resources  ne fait référence à aucun type de données en particulier, mais à une méthode d'abstraction, qui permet de stocker n'importe quel type d'information. Les ressources sont conservées dans une liste spéciale, à l'intérieur de Zend. Chaque entrée dans cette liste a une définition de type correspondante. Zend gère en interne toutes les références de ces ressources. L'accès aux ressources est généralement impossible directement : uniquement en utilisant une API fournie. Aussitôt que toutes les références sur une ressource spécifique sont perdues, la fonction de destruction de la ressource est appelée.

Par exemple, des ressources sont utilisées pour enregistrer des liens avec uen base de données, ou un descripteur de fichier. L'implémentation standard de facto  peut être lue dans le module MySQL, mais d'autres modules, comme celui d'oracle, utilisent aussi les ressources.
Note

En fait, une ressource peut être un pointeur vers n'importe quelles informations dont vous auriez besoin (par exemple, un pointeur sur une structure), et l'utilisateur doit simplement passer une ressource uniques à toutes vos fonctions.

Pour créer une nouvelle ressource, vous devez enregistrer une fonction de destruction de ressource. Comme vous pouvez enregistrer n'importe quel type d'informations dans une ressource, Zend a besoin de savoir comment libérer les ressources réservées, lorsque la ressource ne sera plus utile. Cela se fait en enregistrant votre propre destructeur de ressources, qui sera appelé par Zend lorsqu'il faudra détruire vos données (manuellement, ou automatiquement). En enregistrant votre destructeur de ressource, vous recevrez de Zend un pointeur de type de ressource  pour cette ressource. Ce pointeur sera nécessaire à chaque fois que vous voudrez accéder une ressource de ce type, et il est généralement stocké dans une variable globale static, dans votre extension. Il n'y a pas besoin de prendre en compte la sécurité thread, car vous n'aurez à enregistrer votre destructeur de ressource qu'à l'initialisation du module.

La fonction Zend d'enregistrement est la suivante :


ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);

Il y a deux types différents de destructeurs de ressources, que vous pouvez passer à cette fonction : un pointeur pour les ressources normales, et un pointeur pour les ressources persistantes. Les ressources persistantes sont par exemple utilisées dans les connexions aux bases de données. Lorsque vous enregistrez une ressource, un de ces deux pointeurs devra être fourni. Pour les autres pointeurs, passez simplement NULL.

zend_register_list_destructors_ex accepte les paramètres suivants : > >
ld Fonction de callback pour les destructeurs de ressources normales.
pld Fonction de callback pour les destructeurs de ressources persistantes.
type_name Une chaîne spécifiant le type de vos ressources. C'est toujours mieux d'avoir un nom de ressource unique à travers PHP, pour que les utilisateurs sachent ce qu'ils manipulent sans ambiguité. Ce nom sera affiché avec la fonction var_dump($resource);.
module_number Le module_number est automatiquement disponible dans votre fonction PHP_MINIT_FUNCTION et vous n'avez qu'à le passer ici.
La valeur retournée est un identifiant unique ID pour votre type de ressource .

Le pointeur de destructeur de ressource (soit normal, soit persistant) a le prototype suivant :


void resource_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC);
L'argument rsrc passé est un pointeur sur la structure suivante :

typedef struct _zend_rsrc_list_entry {

     

    void *ptr;

    int type;

    int refcount;


} zend_rsrc_list_entry;
Le membre void *ptr est le pointeur réél sur votre ressource.

Maintenant que nous savons comment tout cela se met en place, nous pouvons définir nos propres ressources, que nous allons enregistrer dans Zend. C'est une simple structure, avec deux membres entiers :


typedef struct {

     

    int resource_link;

    int resource_type;


} my_resource;
Notre destructeur de ressources ressemblera à peut près à ceci :

void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {


    // Vous aurez probablement à transtyper votre pointeur void en

    // une de vos structure


    my_resource *my_rsrc = (my_resource *) rsrc->ptr;


    // Maintenant, faites ce que vous voulez avec votre ressource.

    // fermer des fichiers, libérer de la mémoire, etc...

    // N'oubliez pas de libérer la mémoire de votre ressource elle-même


    do_whatever_needs_to_be_done_with_the_resource(my_rsrc);

}
Note

Une chose importante à mentionner : si votre ressource est une structure plutôt complexe, qui contient elle aussi des pointeurs de mémoire allouée par vos soins, durant l'exécution, vous devez les libérer avant  de libérer la ressource elle-même.

Maintenant que nous avons défini

  • ce qu'est une ressource

  • notre destructeur de ressource

nous pouvons étudier les dernières étapes :
  • créer une variable globale dans l'extension, qui contiendra l'identifiant de ressource, et qui sera ainsi accessible à toutes les fonctions qui en ont besoin.

  • définir le nom de la ressource

  • écrire la fonction de destruction de la ressource

  • et finalement, enregistrer le pointeur


// Quelque part dans votre extension, définissez une variable pour vos ressources enregistrées

    // si vous vous demandez ce que 'le' signifie : c'est simplement 'List Entry', élément de liste, en anglais.

    static int le_myresource;


    // Il est bon de définir votre nom de ressource quelque part

    #define le_myresource_name  "My type of resource"


    [...]


    // Maintenant, définissons le destructeur de pointeur de ressource

    void my_destruction_handler(zend_rsrc_list_entry *rsrc TSRMLS_DC) {


        my_resource *my_rsrc = (my_resource *) rsrc->ptr;

        faite_ce_que_vous_devez_faire_avec_la_ressource(my_rsrc);

    }


    [...]


    PHP_MINIT_FUNCTION(my_extension) {


        // Notez que le 'module_number' est aussi fournit avec la fonction

        // PHP_MINIT_FUNCTION().


        le_myresource = zend_register_resource_destructors_ex(my_destruction_handler, NULL, le_myresource_name, module_number);


        // Vous pouvez aussi enregistrer d'autres ressources, initialiser

        // vos variables globales, etc...

    }

Pour rééllement enregistrer une nouvelle ressource, vous pouvez soit utiliser la fonction zend_register_resource ou bien la macro zend_register_resoure : les deux sont définies dans le fichier zend_list.h . Même si les deux sont identiques, il est toujours mieux de préférer la macro, qui assure une compatibilité ascendante :


int ZEND_REGISTER_RESOURCE(zval *rsrc_result, void *rsrc_pointer, int rsrc_type);
> >
rsrc_result C'est une enveloppe zval * déjà initialisée.
rsrc_pointer Le pointeur de ressource que vous voulez stocker.
rsrc_type Le type que vous avez reçu lorsque vous avez enregistré la fonction de destruction de ressource. Si vous avec suivi la méthode de nommage, cela devait être enregistré dans le_myresource.
La valeur retournée est un entier, qui identifiera sans ambiguité la ressource.

Ce qui se passe en réalité lorsque vous enregistrez une ressource est qu'elle est insérée dans une liste interne de Zend, et que le résultat est simplement stocké dans l'enveloppe zval * :


rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);

     

    if (rsrc_result) {

        rsrc_result->value.lval = rsrc_id;

        rsrc_result->type = IS_RESOURCE;

    }


    return rsrc_id;
La valeur retournée rsrc_id identifie la nouvelle ressource enregistrée. Vous pouez utiliser la macro RETURN_RESOURE pour la retourner à l'utilisateur.

RETURN_RESOURCE(rsrc_id)
Note

C'est une pratique répandue que lorsque vous voulez retourner une ressource immédiatement après sa création, à l'utilisateur, de spécifier return_value comme enveloppe de zval *.

Zend suit le nombre de références qui pointent sur cette ressource. Aussitôt que le nombre de référence est rendu à 0, le destructeur que vous avez enregistré est appelé. L'intérêt évident est que vous n'avez plus à vous soucier de fuite de mémoire, introduites par votre module : il vous suffit de lister toutes les allocations que vous réalisez. Aussitôt que le script n'en aura plus besoin, Zend les retrouvera pour vous, et vous les transmettra.

Maintenant que l'utilisateur a sa ressource, à un moment donné, il va la passer à une de vos fonctions. Le membre value.lval dans l'enveloppe zval * contient la clé de votre ressource, et peut donc être utilisée pour lire la ressource avec cette macro : ZEND_FETCH_RESOURCE:


ZEND_FETCH_RESOURCE(rsrc, rsrc_type, rsrc_id, default_rsrc_id, resource_type_name, resource_type)
> >
rsrc Ceci est votre pointeur, qui pointe sur vos ressource déjà réservées.
rsrc_type C'est l'argument de transtypage de votre pointeur, c'est à dire myresource *.
rsrc_id Ceci est l,adresse de l'enveloppe zval *, que l'utilisateur à passé à votre fonction, c'est à dire &z_resource si zval *z_resource est fourni.
default_rsrc_id Cet entier spécifie l'identifiant de ressource ID si aucune ressource n'a pu être lue, ou bien -1.
resource_type_name C'est le nom de la ressource demandée. C'est une chaîne, et elle est utilisée lorsque la ressource n'a pu être trouvée, ou bien est invalide. Elle formera un message d'erreur significatif.
resource_type Le type de ressource resource_type que vous avez obtenu lors de l'enregistrement de votre fonction de destruction de ressource. Dans notre exemple, c'était le_myresource.
Cette macro n'a pas de valeur de retour. Elle est faite pour le confort des développeurs, et prend en charge le passage des arguments TSRMLS, et vérifie aussi si la ressource peut être lue. Il affiche un message d'alerte et termine la fonctoin PHP avec la valeur NULL si un problème est survenu lors de la lecture de la ressource.

Pour forcer la suppression d'une ressource dans une liste, utilisez la fonction zend_list_delete. Vous pouvez aussi forcer l'augmentation du compteur de référence si vous savez que vous créer une autre référence à une valeur déjà alloueé (par exemple, si vous réutilisez automatiquement une connexion par défaut à une base de données). Dans ce cas, utilisez la fonction zend_list_addref. Pour rechercher des ressources déjà allouées, utilisez zend_list_find. L'API complète est disponible dans le fichier zend_list.h .


Chapitre précédentChapitre suivantAccueil nexen.net