slot deposit pulsa slot mahjong slot gacor slot gacor slot gacor resmi slot gacor 2025 slot gacor terpercaya slot gacor 2025 slot gacor hari ini slot gacor hari ini slot gacor hari ini
PHP7扩展开发之常量定义
17611538698
webmaster@21cto.com

PHP7扩展开发之常量定义

资讯 0 4104 2017-01-14 12:00:44
未标题-1.png

 

社区导读:本文为苍老师PHP扩展开发之常量定义篇。大家都知道在PHP中如何定义常量,但是如何在PHP7.x的扩展开发中定义常量呢?看了本文,相信对想从事PHP扩展开发的同学有所助益。



各位好,相信大家知道如何在PHP扩展中定义一个常量。在脚本中,定义常量的代码如下之所示:
<?php
define("__ARR__", array('2', 'site'=>"www.bo56.com"));
define("__SITE__", "www.bo56.com", true);
define("say__SITE__", "bo56.com");
var_dump(__ARR__);
var_dump(__site__);
var_dump(say__SITE__);
?>

接下来,农学家讲豆种,咱们举粒说明。下面介绍的就是在PHP扩展中定义三个常量,上面PHP代码中的三个常量定义(const define)。
 
基础代码

下面这个扩展,我们将在say扩展的 PHP_MINIT_FUNCTION(say)方法上增加相应的代码。say扩展相关代码大家请看以前的文章或到博客bo56.com上查看。

我们要增加的代码如下:
//增加两个方法
//释放hash
static void say_hash_destroy(HashTable *ht)
zend_string *key;
zval *element;
if (((ht)->u.flags & HASH_FLAG_INITIALIZED)) {
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, element) {
if (key) {
free(key);
}
switch (Z_TYPE_P(element)) {
case IS_STRING:
free(Z_PTR_P(element));
break;
case IS_ARRAY:
say_hash_destroy(Z_ARRVAL_P(element));
break;
}
} ZEND_HASH_FOREACH_END();
free(HT_GET_DATA_ADDR(ht));
}
free(ht);
}
//释放数组和字符串
static void say_entry_dtor_persistent(zval *zvalue)
if (Z_TYPE_P(zvalue) == IS_ARRAY) {
say_hash_destroy(Z_ARRVAL_P(zvalue));
} else if (Z_TYPE_P(zvalue) == IS_STRING) {
zend_string_release(Z_STR_P(zvalue));
}
}
//PHP_MINIT_FUNCTION(say)方法的PHP扩展源码: 扩展初始化的调用此方法
PHP_MINIT_FUNCTION(say)
{
zend_constant c;
zend_string *key;
zval value;
ZVAL_NEW_PERSISTENT_ARR(&c.value);
zend_hash_init(Z_ARRVAL(c.value), 0, NULL,
(dtor_func_t)say_entry_dtor_persistent, 1);
add_index_long(&c.value, 0, 2);
key = zend_string_init("site", 4, 1);
ZVAL_STR(&value, zend_string_init("www.bo56.com", 12, 1));
zend_hash_update(Z_ARRVAL(c.value), key, &value);
c.flags = CONST_CS|CONST_PERSISTENT;
c.name = zend_string_init("__ARR__", 7, 1);
c.module_number = module_number;
zend_register_constant(&c);
REGISTER_STRINGL_CONSTANT("__SITE__", "www.bo56.com", 12, CONST_PERSISTENT);
REGISTER_NS_STRINGL_CONSTANT("say", "__SITE__", "bo56.com", 8, CONST_CS|CONST_PERSISTENT);
}
//扩展卸载的时候调用此方法
PHP_MSHUTDOWN_FUNCTION(say)
{
zval *val;
val = zend_get_constant_str("__ARR__", 7);
say_hash_destroy(Z_ARRVAL_P(val));
ZVAL_NULL(val);
return SUCCESS;
}
代码说明

一般情况下,在扩展中只建议定义null,bool,long,double,string几种类型的常量。因为内核只提供了这几种类型的宏方法。

常量定义的宏方法在Zend/zend_constants.h文件中。想定义一个常量,很简单,只要调用对应的宏方法即可。如:
REGISTER_STRINGL_CONSTANT("__SITE__", "www.bo56.com", 12, CONST_PERSISTENT);
宏方法的最后一个参数是一些标识符。
CONST_PERSISTENT 表示为持久的。常驻内存。
CONST_CS 表示为区分大小写。
注意我们上面定义常量时使用的是__SITE__,但是调用的时候使用的是__site__。

还有一套可以指定命名空间的宏方法。宏方法中带NS。如:
REGISTER_NS_STRINGL_CONSTANT("say", "__SITE__", "bo56.com", 8, CONST_CS|CONST_PERSISTENT);
第一个参数就是命名空间。

为了展示常量定义的一些细节。我们定义了一个__ARR__常量。
ZVAL_NEW_PERSISTENT_ARR(&c.value);我们想让__ARR__为持久的。所以使用ZVAL_NEW_PERSISTENT_ARR创建一个数组。

数组创建完后,我们需要初始化。初始化的代码就是
zend_hash_init(Z_ARRVAL(c.value), 0, NULL,
(dtor_func_t)say_entry_dtor_persistent, 1);
参数中的say_entry_dtor_persistent是一个析构函数,用于释放数组的元素。

到这里,如果编译运行。当程序执行结束的时候,你会发现一个致命错误。错误信息如下:
Fatal error: Internal zval's can't be arrays, objects or resources inUnknown on line 0

由于在程序执行完毕,内部zval释放的时候,会进行类型检测。如果发现是array object或者resources,则会报错。可以查看Zend/zend_variables.c文件中_zval_internal_dtor方法。
为了解决这个问题,我们需要手动释放刚刚创建的__ARR__相关的数组。

模块卸载时执行的方法,是优先Zend内部zval释放方法之前调用的。因此,我们只要在PHP_MSHUTDOWN_FUNCTION(say)方法中手动释放。不再让Zend去释放就可以解决了。

看了以上文章,相信大家对PHP常量定义已经清晰。咱们下回开发接着谈。

评论