最近、私は PHP7 のソースコードを見て、このバージョンに基づいて PHP 拡張機能を開発する方法を学んでいます (以前は古いバージョンでの拡張機能開発の経験があまりなかったので、新しいエンジンは出発点を改善できます) )。ここではいくつかのメモを示します。
反復コールバック関数を作成します。 2 つのコールバック形式があります:
// 传值int callback(zval *val) { zvaltmp; // 增加一个临时 zval 避免 convert_to_string 污染原元素 ZVAL_COPY(&tmp, val); // 复制 val 的值,在 PHP5 中,需要用 zval_copy_ctor 并重置引用计数,现在貌似不用了 convert_to_string(&tmp); // 字符串类型转换 // 目的很简单,只是打印出来 php_printf("The value is: [ "); PHPWRITE(Z_STRVAL(tmp), Z_STRLEN(tmp)); php_printf(" ]"); zval_dtor(&tmp); // 主动释放临时 zval,不然会内存泄漏 return ZEND_HASH_APPLY_KEEP;} // 传键和值int callback_args(zval *val, int num_args, va_listargs, zend_hash_key *hash_key) { zvaltmp = *val; ZVAL_COPY(&tmp, val); convert_to_string(&tmp); // 打印键值对结果 php_printf("The key is : [ "); if (hash_key->key) { PHPWRITE(ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key)); } else { php_printf("%ld", hash_key->h); } php_printf(" ], the value is: [ "); PHPWRITE(Z_STRVAL(tmp), Z_STRLEN(tmp)); php_printf(" ]"); zval_dtor(&tmp); return ZEND_HASH_APPLY_KEEP;}
zval *val は配列内の要素の値 zval、hash_key は要素のキー、両方ともポインタ、および構造zend_hash_key は zend_hash.h で定義されています
typedef struct _zend_hash_key { zend_ulong h; // 数字键 zend_string *key; // 字符串键} zend_hash_key;
コールバック関数は 3 つの定数値を返すことができます:
Constant | Description |
---|---|
ZEND_HASH_APPLY_KEEP | この値を返すと現在のループが完了し、HashTable での反復が継続されます。次の値、これは待機します continue の実行と同等です; |
ZEND_HASH_APPLY_STOP | この値を返すと反復が中断され、foreach() 制御ブロックでの Break の実行と同等です; |
ZEND_HASH_APPLY_REMOVE | Simi lar から ZEND_H ASH_APPLY_KEEP、これ戻り値は次の反復にジャンプしますが、この戻り値によって現在の要素が元の HashTable から削除されることもあります |
PHP 関数 foo を定義するとします。
PHP_FUNCTION(foo){ // 从参数中获取 arr zval *arr; if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &arr) == FAILURE) { RETURN_NULL(); } // 遍历值 zend_hash_apply(ZARRVAL_P(arr), callback); // 遍历键和值 zend_hash_apply_with_arguments(Z_ARRVAL_P(arr), callback_args, 0);}
Z_ARRVAL_P ユーザーは zval 構造体を返します。 value.arr ポインタ