php的扩展与嵌入--php扩展中的数组和哈希表1_PHP教程
在php中,数组的底层实现就是哈希表,都是以key-value的形式出现的。在php的Zend引擎中,针对不同的哈希表操作,都有着专门的对哈希表进行操作的api。
Creation
对于哈希表而言,每次初始化的方式都是一样的,都由下面这个函数zend_hash_init来完成:
int zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent)
ALLOC_HASHTABLE(ht),相当于ht = emalloc(sizeof(HashTable));。
nSize是哈希表的最大元素数,是为了提前申请好内存考虑的。如果它不是2的指数倍,会根据下式增长nSize = pow(2, ceil(log(nSize, 2)));,比如如果给了5,那么会增长到8.这个应该是为了内存管理比较方便所采用的机制。
pHashFunction属于以前版本的zend eigine函数,在新版本中一直设为NULL即可。
pDestructor指向当哈希表中的元素被删掉的时候(zend_hash_del() zend_hash_update())所调用的方法的入口,也就是一个相应的回调函数。假如说给定了method_name函数,那么在函数实现的时候:
void method_name(void *pElement)
pElement指向被删掉的元素
persistent这个是一个标志位,表示是否是持久型的哈希表,持久型的数据是独立于请求之外的,不会在RSHUTDOWN的时候被注销掉。但是如果设1的话,那么ht在申请内存的时候一定要使用pemalloc().
举个例子:在每个php请求生命周期中对symbol_table初始化的时候都会看到zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
每当unset的时候,相应的存储在哈希表中的zval*都被发送给zval_ptr_dtor()进行销毁。
Population:
有四种主要的插入和更新哈希表中数据的函数:
int zend_hash_add(HashTable *ht, char *arKey, uint nKeyLen, void *pData, uint nDataSize, void **pDest); int zend_hash_update(HashTable *ht, char *arKey, uint nKeyLen, void *pData, uint nDataSize, void **pDest); int zend_hash_index_update(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest); int zend_hash_next_index_insert(HashTable *ht, void *pData, uint nDataSize, void **pDest);
zend_hash_add(fooHashTbl, "bar", sizeof("bar"), &barZval, sizeof(zval*), NULL);
就把相应key值和对应的表值加入到了hashtable中去了。
add和update唯一的区别是如果key已经存在的话,add会失败的。
后两个函数是向ht中添加数字索引的数据。
zend_hash_next_index_insert()函数不需要索引值参数,而是自己直接计算出下一个数字索引值。
而如果想自己获得下一个元素的数字索引值也可以通过zend_hash_next_free_element()来获得索引。
ulong nextid = zend_hash_next_free_element(ht);
zend_hash_index_update(ht, nextid, &data, sizeof(data), NULL);
上面这段代码就相当于:
zend_hash_next_index_insert(HashTable *ht, &data,sizeof(data),NULL).
其中pDest参数可以用来存储新加入的元素的地址值。
Recall:查找
一般来说,有两种获得哈希表中数据的方法:
int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData); int zend_hash_index_find(HashTable *ht, ulong h, void **pData);
在下面的这个例子中可以更清楚的看到:
void hash_sample(HashTable *ht, sample_data *data1) { sample_data *data2; ulong targetID = zend_hash_next_free_element(ht);//获取下一个索引的位置 if (zend_hash_index_update(ht, targetID, data1, sizeof(sample_data), NULL) == FAILURE) {//把数据data1插入到哈希表的下一个索引的位置中去 /* Should never happen */ return; } if(zend_hash_index_find(ht, targetID, (void **)&data2) == FAILURE) {//利用id去寻找哈希表中的值,如果找到的话把值放在data2中。 /* Very unlikely since we just added this element */ return; } /* data1 != data2, however *data1 == *data2 */ }
int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLen); int zend_hash_index_exists(HashTable *ht, ulong h);
if (zend_hash_exists(EG(active_symbol_table), "foo", sizeof("foo"))) {//确定活动的符号表中是否存在foo变量 /* $foo is set */ } else { /* $foo does not exist */ }
Quick Population and Recall 当需要对同一个字符串的key进行许多操作的时候比如先检测有没有,然后插入再修改之类的,可以使用zend_get_hash_value来进行提速。这个函数的返回值可以和quick系列的函数使用,从而达到加速的目的。因为不需要再重复计算字符串的散列值,而是直接使用已有的散列值。
ulong zend_get_hash_value(char *arKey, uint nKeyLen);
int zend_hash_quick_add(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void *pData, uint nDataSize, void **pDest); int zend_hash_quick_update(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void *pData, uint nDataSize, void **pDest); int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval, void **pData); int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLen, ulong hashval);
下面给出了一个在两个哈希表之间进行数据拷贝的例子:
void php_sample_hash_copy(HashTable *hta, HashTable *htb, char *arKey, uint nKeyLen TSRMLS_DC) { ulong hashval = zend_get_hash_value(arKey, nKeyLen);//获得用来加速的散列值hashval zval **copyval; if (zend_hash_quick_find(hta, arKey, nKeyLen, hashval, (void**)©val) == FAILURE) {//首先要在hta table里面找到相应的元素,并且存储在copyval中。 /* arKey doesn't actually exist */ return; } /* The zval* is about to be owned by another hash table */ (*copyval)->refcount__gc++;//相应zval*变量的引用次数+1 zend_hash_quick_update(htb, arKey, nKeyLen, hashval, copyval, sizeof(zval*), NULL);//把从hta中拿来的copyval放在htb里面。 }
注意并没有zend_hash_del函数。
Copy and Merging 有三个方法可以进行数据的拷贝,先来看第一个:
typedef void (*copy_ctor_func_t)(void *pElement); void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
tmp这里放NULL,低版本才会用到。
size的话代表每个元素的大小,一般是sizeof(zval *)。
void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
下面的这一组函数允许使用一个归并的检查进行选择性的复制:
typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam); void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
下面给出了一个应用的例子:
zend_bool associative_only(HashTable *ht, void *pData, zend_hash_key *hash_key, void *pParam) { /* True if there's a key, false if there's not */ return (hash_key->arKey && hash_key->nKeyLength);//字符串类型的key,因为存在nKeyLength } void merge_associative(HashTable *target, HashTable *source) { zend_hash_merge_ex(target, source, zval_add_ref, sizeof(zval*), associative_only, NULL); }

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

PHP的SNMP擴充是一種讓PHP能夠透過SNMP協定與網路設備進行通訊的擴充功能。使用此擴展可以方便地獲取和修改網路設備的配置信息,例如路由器、交換器等設備的CPU、內存、網絡接口等信息,也可以進行諸如開關設備端口等控制操作。本文將介紹SNMP協定的基礎知識、PHP的SNMP擴充的安裝方法以及如何在PHP中使用SNMP擴充進行網路設備的監控與控制。一、SN

從頭到尾:如何使用php擴充cURL進行HTTP請求引言:在Web開發中,經常需要與第三方API或其他遠端伺服器進行通訊。而使用cURL進行HTTP請求是一種常見且強大的方式。本文將介紹如何使用php擴充cURL來執行HTTP請求,並提供一些實用的程式碼範例。一、準備工作首先,請確保php已安裝cURL擴充。可以在命令列執行php-m|grepcurl查

PHP與HTML結合是網頁開發中常見的技術,透過PHP可以在HTML文件中嵌入動態內容、實現輔助功能等,大大提高了網站的互動性和可自訂性。本文將介紹三種嵌入程式碼的技巧,並提供具體的程式碼範例供參考。一、使用PHP標記嵌入程式碼最常見的方式是使用PHP標記()將PHP程式碼嵌入HTML檔案中,實現動態內容的顯示。例如,可以使用PHP

若要擴充PHP函數功能,可以使用擴充和第三方模組。擴充功能提供附加函數和類,可透過pecl套件管理器安裝和啟用。第三方模組提供特定功能,可透過Composer套件管理器安裝。實作案例包括使用擴充解析複雜JSON資料和使用模組驗證資料。

1.UncaughtError:Calltoundefinedfunctionmb_strlen();出現如上錯誤時,說明我們沒裝上mbstring擴展;2.進入PHP安裝目錄cd/temp001/php-7.1.0/ext/mbstring3.啟動phpize(/usr/local/bin /phpize或/usr/local/php7-abel001/bin/phpize)指令來安裝php擴充4../configure--with-php-config=/usr/local/php7-abel

如何使用極光推播擴展,在PHP應用中實現大量訊息推播功能在行動應用的開發中,訊息推播是一項非常重要的功能。極光推送是一種常用的訊息推播服務,提供了豐富的功能和介面。本文將介紹如何使用極光推播擴充功能在PHP應用中實現大量訊息推播功能。第一步:註冊極光推播帳號並取得API金鑰首先,我們需要在極光推播官網(https://www.jiguang.cn/push)註冊

PHP是一種流行的伺服器端語言,可以用來開發網頁應用程式和處理檔案。 PHP的ZipArchive擴充功能是一個強大的工具,可以在PHP中操作zip檔。在這篇文章中,我們將介紹如何使用PHP的ZipArchive擴充功能來建立、讀取和修改zip檔。一、安裝ZipArchive擴充功能在使用ZipArchive擴充功能之前,需要確保已經安裝了這個擴充功能。安裝方法如下:1.安

PHP的POSIX擴充是一組允許PHP與POSIX相容作業系統互動的函數與常數。 POSIX(PortableOperatingSystemInterface)是一組作業系統介面標準,旨在允許軟體開發人員編寫可在各種UNIX或UNIX類別作業系統上運行的應用程式。本文將介紹如何使用PHP的POSIX擴展,包括安裝和使用。一、安裝PHP的POSIX擴充在
