Résumé de la première partie
Dans la
première partie, j'ai fait une extension vierge
, je l'ai fait fonctionner correctement dans l'IDE Clion, j'ai écrit une fonction analogique, my_array_fill (), et vérifié son opérabilité en php.
Et maintenant
Maintenant, je vais mettre le
code de la bibliothèque libtrie dans notre extension.
Je vais parler un peu de la façon dont vous pouvez faire fonctionner les anciennes extensions php5 en php7.
De plus, je ferai quelques fonctions de base de cette bibliothèque en php et vérifierai ce qui s'est passé.
On y va
Obtenez le code libtrie dans notre extension
Je vais dans le répertoire des extensions
cd ~/Documents/libtrie/
Clonage du référentiel libtrie
git clone https:

J'ouvre le fichier avec le code d'extension
php_libtrie.c
et le fichier avec le code de bibliothèque
libtrie/src/libtrie.c
.

Je vais utiliser ce dernier pour vérifier les noms et la syntaxe des fonctions.
Les fonctions créées dans php que j'utiliserai sont les mêmes que dans la bibliothèque elle-même.
Tout d'abord, vous devez inclure le fichier d'en-tête de bibliothèque dans le code de notre extension.
Nous écrivons dans php_libtrie.c:
#include "libtrie/src/libtrie.h"
Fonction Yatrie_new
Je fais la première fonction qui créera l'arbre de préfixe. Dans la bibliothèque ça s'appelle
trie_s *yatrie_new(uint32_t max_nodes, uint32_t max_refs, uint32_t max_deallocated_size) {...}
Comme vous pouvez le voir dans le code, la fonction prend 3 arguments numériques à l'entrée et renvoie un pointeur sur la structure
trie_s
. Autrement dit, renvoie un lien vers l'arbre de préfixe créé.
Afin de tirer notre arborescence de préfixes en PHP, PHP a un type de données de ressource spécial. Lorsqu'une fonction est exécutée en PHP
fopen("filename.ext");
Parlant en langage C, le programme demande au système d'exploitation d'ouvrir le fichier spécifié, crée un pointeur vers ce fichier, qui sous la forme d'une ressource et retourne en dehors de PHP.
Nous ferons de même avec notre arbre.
Faisons une fonction dans php_libtrie.c:
Code de fonction PHP_FUNCTION (yatrie_new) { /* */ trie_s *trie; // zend_long max_nodes; // - zend_long max_refs; /* - . * . - +25% . * , OpenCorpora ~3. 5. 5. */ zend_long max_deallocated_size; /* * . 96 , 1 , 95. * 95, , * . 94. */ // PHP if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &max_nodes, &max_refs, &max_deallocated_size) == FAILURE) { RETURN_FALSE; } // trie = yatrie_new((uint32_t)max_nodes, (uint32_t)max_refs, (uint32_t)max_deallocated_size); // - if (!trie) { RETURN_NULL(); } // 2 /* zend_register_resource() Zend, * le_libtrie, ZVAL_RES() * zval return_value */ ZVAL_RES(return_value, zend_register_resource(trie, le_libtrie)); }
Vous devez maintenant ajouter la fonction créée au tableau des fonctions d'extension, sinon la fonction ne sera pas visible depuis PHP.
PHP_FE(yatrie_new, NULL)

Pour le rendre beau, j'ajouterai une déclaration de fonction au fichier d'en-tête. Ce n'est pas nécessaire, car nos fonctions PHP n'interagissent pas entre elles, mais je préfère quand même déclarer toutes les fonctions dans le fichier d'en-tête.
Ajoutez simplement les lignes:
PHP_FUNCTION(confirm_libtrie_compiled)
dans le fichier php_libtrie.h. N'importe où entre:
#ifndef PHP_LIBTRIE_H #define PHP_LIBTRIE_H
et
#endif

PHP a créé le destructeur de ressources
La fonction yatrie_new () créée crée un arbre et enregistre également une ressource PHP. Nous avons maintenant besoin d'une fonction qui fermera la ressource créée et libérera la mémoire occupée par l'arborescence des préfixes.
static void php_libtrie_dtor(zend_resource *rsrc TSRMLS_DC) {
Étant donné que la fonction est interne au tableau de fonctions d'extension, elle n'est pas incluse. Ajoutez sa déclaration à php_libtrie.h:

Vous devez maintenant enregistrer la fonction destructrice créée en PHP. Cela se fait via une fonction spéciale d'initialisation d'extension. Auparavant, cette fonction renvoyait simplement SUCCESS immédiatement. Il faut y ajouter l'enregistrement du destructeur.
// PHP trie PHP_MINIT_FUNCTION (libtrie) { le_libtrie = zend_register_list_destructors_ex( php_libtrie_dtor, NULL, PHP_LIBTRIE_RES_NAME, module_number); return SUCCESS; }

Supprimer la fonction d'arborescence créée
Tout comme la fonction
fopen()
a quelques
fclose()
, ma fonction de création d'arbre devrait avoir une petite amie qui l'équilibrera.
Code /** * @brief * @param trie : resource * @return true/false : bool */ PHP_FUNCTION (yatrie_free) { zval *resource; // zval // if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &resource) == FAILURE) { RETURN_FALSE; } /* , zend_resource, * zval. Z_RES_P() */ if (zend_list_close(Z_RES_P(resource)) == SUCCESS) { // true return_vale return RETURN_TRUE; } // false return_vale return RETURN_FALSE; }
Ajoutez une fonction au tableau des fonctions d'extension:
PHP_FE(yatrie_free, NULL)
Ajoutez la déclaration de fonction au fichier d'en-tête:
PHP_FUNCTION(yatrie_free)

Comme vous pouvez le voir sur la capture d'écran, j'ai ajouté le nom interne de la ressource en PHP au fichier d'en-tête, ainsi que les macros PHP5, qui pour une raison quelconque ont été supprimées de PHP7. Je ne les utilise pas, mais si quelqu'un le souhaite, vous pouvez facilement créer l'extension PHP5 en PHP7.
#define PHP_LIBTRIE_VERSION "0.1.0" #define PHP_LIBTRIE_RES_NAME "libtrie data structure"
Fonction ajouter des mots dans trie
Faisons maintenant l'ajout d'un mot à l'arbre des préfixes.
Code /** * @brief trie node_id * @param trie : resource * @param word : string * @return node_id : int */ PHP_FUNCTION (yatrie_add) { trie_s *trie; // zval *resource; // zval unsigned char *word = NULL; // size_t word_len; // word uint32_t node_id; //id , // if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &resource, &word, &word_len) == FAILURE) { RETURN_FALSE } /* PHP, : * 1 PHP ( zval, ), * 2 * * 3 id , * void *, trie_s * * PHP5 ZEND_FETCH_RESOURCE(), - PHP7. */ trie = (trie_s *) zend_fetch_resource(Z_RES_P(resource), PHP_LIBTRIE_RES_NAME, le_libtrie); /* trie * - * - id , * - . */ node_id = yatrie_add(word, 0, trie); // RETURN_LONG(node_id); }
- Ajoutez une entrée au tableau de fonctions:
PHP_FE(yatrie_add, NULL)
- Ajoutez une déclaration au fichier d'en-tête:
PHP_FUNCTION(yatrie_add)
La fonction pour sortir tous les mots du dictionnaire
Maintenant, créons une fonction qui sélectionnera tous les mots de l'arborescence des préfixes et les affichera en PHP sous forme de tableau.
Code /** * @brief , , * , * @param trie : resource * @param node_id : int * @param head () : string , * * @return array */ PHP_FUNCTION (node_traverse) { trie_s *trie; // trie words_s *words; // trie zval * resource; // zval zend_long node_id; // unsigned char *head = NULL; // size_t head_len; // // PHP if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|s", &resource, &node_id, &head, &head_len) == FAILURE) { RETURN_NULL(); // null } // trie = (trie_s *) zend_fetch_resource(Z_RES_P(resource), PHP_LIBTRIE_RES_NAME, le_libtrie); // trie node_traverse() words_s // words = (words_s *) calloc(1, sizeof(words_s)); words->counter = 0; // 0 // 1 string_s *head_libtrie = calloc(1, sizeof(string_s)); // head if(head != NULL) { head_libtrie->length = (uint32_t)head_len; // memcpy(&head_libtrie->letters, head, head_len); // head_libtrie } // trie node_traverse(words, (uint32_t) node_id, head_libtrie, trie); // PHP , words array_init_size(return_value, words->counter); // php while (words->counter--) { // trie , // uint8_t dst[256]; // libtrie decode_string(dst, words->words[words->counter]); // Zend API, php string char * add_next_index_string(return_value, (const char *) dst); } // words head_libtrie free(words); free(head_libtrie); }
- Ajoutez une entrée au tableau de fonctions:
PHP_FE(node_traverse, NULL)
- Ajoutez une déclaration au fichier d'en-tête:
PHP_FUNCTION(node_traverse)
Ensemble d'extension
Étant donné que l'extension utilise désormais des fichiers de bibliothèque tiers, ces fichiers doivent également être compilés. J'ouvre le fichier config.m4 et j'y ajoute les 2 fichiers sources libtrie:
libtrie/src/libtrie.c
libtrie/src/single_list.c
Voici le contenu complet du fichier après les modifications.
config.m4 PHP_ARG_ENABLE(libtrie, whether to enable libtrie support, [ --enable-libtrie Enable libtrie support]) if test "$PHP_LIBTRIE" != "no"; then

Vous devez maintenant refaire le script ./configure. Je cours depuis le répertoire racine de l'extension:
phpize && ./configure
Maintenant je construis l'extension:
make
Test
Pour le test, il est préférable de faire un script php afin de ne pas trop écrire dans la console. Je vais le faire:
nano yatrie_test.php
Et voici le contenu du fichier:
<?php echo "C 500 500 \n\n"; $trie = yatrie_new(500, 500, 100); echo "!\n , id \$nodes\n"; $nodes[] = yatrie_add($trie, ""); $nodes[] = yatrie_add($trie, ""); $nodes[] = yatrie_add($trie, ""); echo " .\n 2 , 2.\n 3 , 2 ,\n 1 \n"; print_r($nodes); print_r(node_traverse($trie, 0)); yatrie_free($trie);
Nous exécutons dans la console:
php -d extension=modules/libtrie.so yatrie_test.php
Voici ce que vous devriez obtenir:

Nous prenons le code source de l'extension
d'ici . Ne soyez pas timide et mettez des astérisques :-)