Ringkasan bagian pertama
Pada bagian
pertama, saya membuat ekstensi kosong, membuatnya bekerja dengan benar di IDE Clion, menulis fungsi analog, my_array_fill (), dan memeriksa kinerjanya di php.
Apa sekarang?
Sekarang saya akan memasukkan
kode libtrie library ke ekstensi kita.
Saya akan berbicara sedikit tentang bagaimana Anda dapat membuat ekstensi php5 lama berfungsi di php7.
Selanjutnya saya akan membuat beberapa fungsi dasar dari perpustakaan ini di php dan memeriksa apa yang terjadi.
Ayo pergi
Dapatkan kode libtrie di ekstensi kami
Saya pergi ke direktori ekstensi
cd ~/Documents/libtrie/
Mengkloning repositori libtrie
git clone https:

Saya membuka file dengan kode ekstensi
php_libtrie.c
dan file dengan kode perpustakaan
libtrie/src/libtrie.c
.

Saya akan menggunakan yang terakhir untuk memeriksa nama dan sintaks fungsi.
Fungsi-fungsi yang dibuat dalam php yang akan saya gunakan sama dengan di perpustakaan itu sendiri.
Pertama-tama, Anda perlu memasukkan file header perpustakaan dalam kode ekstensi kami.
Kami menulis di php_libtrie.c:
#include "libtrie/src/libtrie.h"
Fungsi Yatrie_new
Saya membuat fungsi pertama yang akan membuat pohon awalan. Di perpustakaan itu disebut
trie_s *yatrie_new(uint32_t max_nodes, uint32_t max_refs, uint32_t max_deallocated_size) {...}
Seperti yang dapat Anda lihat dari kode, fungsi mengambil 3 argumen numerik pada input dan mengembalikan pointer ke struktur
trie_s
. Sederhananya, mengembalikan tautan ke pohon awalan yang dibuat.
Untuk menarik pohon awalan kami ke dalam PHP, PHP memiliki tipe data sumber daya khusus. Ketika suatu fungsi dieksekusi dalam PHP
fopen("filename.ext");
Berbicara dalam bahasa C, program meminta sistem operasi untuk membuka file yang ditentukan, membuat pointer ke file ini, yang dalam bentuk sumber daya dan kembali ke luar ke PHP.
Kami akan melakukan hal yang sama dengan pohon kami.
Mari kita membuat fungsi di php_libtrie.c:
Kode fungsi 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)); }
Sekarang Anda perlu menambahkan fungsi yang dibuat ke array fungsi ekstensi, jika tidak fungsi tersebut tidak akan terlihat dari PHP.
PHP_FE(yatrie_new, NULL)

Agar terlihat indah, saya akan menambahkan deklarasi fungsi ke file header. Ini tidak perlu, karena fungsi PHP kami tidak berinteraksi satu sama lain, tetapi saya masih lebih suka untuk mendeklarasikan semua fungsi dalam file header.
Cukup tambahkan baris:
PHP_FUNCTION(confirm_libtrie_compiled)
ke file php_libtrie.h. Di mana saja di antara:
#ifndef PHP_LIBTRIE_H #define PHP_LIBTRIE_H
dan
#endif

PHP menciptakan destruktor sumber daya
Fungsi yatrie_new () yang dibuat membuat pohon dan juga mendaftarkan sumber daya PHP. Sekarang kita membutuhkan fungsi yang akan menutup sumber daya yang dibuat dan membebaskan memori yang ditempati oleh pohon awalan.
static void php_libtrie_dtor(zend_resource *rsrc TSRMLS_DC) {
Karena fungsi internal untuk berbagai fungsi ekstensi, itu tidak termasuk. Tambahkan deklarasi ke php_libtrie.h:

Sekarang Anda perlu mendaftarkan fungsi destruktor yang dibuat di PHP. Ini dilakukan melalui fungsi inisialisasi ekstensi khusus. Sebelum ini, fungsi ini langsung mengembalikan SUKSES. Perlu menambahkan pendaftaran destruktor di sana.
// 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; }

Hapus fungsi pohon yang dibuat
Sama seperti fungsi
fopen()
memiliki beberapa
fclose()
, jadi fungsi pembuatan pohon saya harus memiliki pacar yang akan menyeimbangkannya.
Kode /** * @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; }
Tambahkan fungsi ke array fungsi ekstensi:
PHP_FE(yatrie_free, NULL)
Tambahkan deklarasi fungsi ke file header:
PHP_FUNCTION(yatrie_free)

Seperti yang dapat Anda lihat di tangkapan layar, saya menambahkan nama internal sumber daya dalam PHP ke file header, serta makro PHP5, yang karena alasan tertentu dihapus dari PHP7. Saya tidak menggunakannya, tetapi jika seseorang ingin menggunakannya, Anda dapat dengan mudah membangun ekstensi PHP5 ke PHP7.
#define PHP_LIBTRIE_VERSION "0.1.0" #define PHP_LIBTRIE_RES_NAME "libtrie data structure"
Fungsi menambahkan kata dalam trie
Sekarang mari kita membuat fungsi menambahkan kata ke pohon awalan.
Kode /** * @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); }
- Tambahkan entri ke berbagai fungsi:
PHP_FE(yatrie_add, NULL)
- Tambahkan deklarasi ke file header:
PHP_FUNCTION(yatrie_add)
Fungsi untuk mengeluarkan semua kata dari kamus
Sekarang mari kita membuat fungsi yang akan memilih semua kata dari pohon awalan dan mengeluarkannya dalam PHP sebagai array.
Kode /** * @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); }
- Tambahkan entri ke berbagai fungsi:
PHP_FE(node_traverse, NULL)
- Tambahkan deklarasi ke file header:
PHP_FUNCTION(node_traverse)
Perakitan ekstensi
Karena ekstensi sekarang menggunakan file perpustakaan pihak ketiga, file-file ini juga harus dikompilasi. Saya membuka file config.m4 dan menambahkan file sumber 2 libtrie di sana:
libtrie/src/libtrie.c
libtrie/src/single_list.c
Berikut adalah isi lengkap file setelah perubahan.
config.m4 PHP_ARG_ENABLE(libtrie, whether to enable libtrie support, [ --enable-libtrie Enable libtrie support]) if test "$PHP_LIBTRIE" != "no"; then

Sekarang Anda perlu melakukan kembali skrip ./configure. Saya menjalankan dari direktori root ekstensi:
phpize && ./configure
Sekarang saya sedang membangun ekstensi:
make
Pengujian
Untuk pengujian, yang terbaik adalah membuat skrip php agar tidak banyak menulis di konsol. Saya akan melakukan ini:
nano yatrie_test.php
Dan ini adalah isi file:
<?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);
Kami mengeksekusi di konsol:
php -d extension=modules/libtrie.so yatrie_test.php
Inilah yang harus Anda dapatkan:

Kami mengambil kode sumber ekstensi
dari sini . Jangan malu dan letakkan tanda bintang :-)