参考引文http://www.cunmou.com/phpbook/index.md,今天来做一个php源码的改动验证。
引文2.1中提及:
这样我们便可以猜测一下php内核是如何实现gettype这个函数了,代码如下:
//开始定义php语言中的函数gettype
PHP_FUNCTION(gettype)
{
//这个arg间接指向就是我们传给gettype函数的参数。是一个zval**结构
//所以我们要对他使用__PP后缀的宏。
zval **arg;
//这个if的操作主要是让arg指向参数~
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
return;
}
//调用Z_TYPE_PP宏来获取arg指向zval的类型。
//然后是一个switch结构,RETVAL_STRING宏代表这gettype函数返回的字符串类型的值
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
RETVAL_STRING("NULL", 1);
break;
case IS_BOOL:
RETVAL_STRING("boolean", 1);
break;
case IS_LONG:
RETVAL_STRING("integer", 1);
break;
case IS_DOUBLE:
RETVAL_STRING("double", 1);
break;
case IS_STRING:
RETVAL_STRING("string", 1);
break;
case IS_ARRAY:
RETVAL_STRING("array", 1);
break;
case IS_OBJECT:
RETVAL_STRING("object", 1);
break;
case IS_RESOURCE:
{
char *type_name;
type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
if (type_name) {
RETVAL_STRING("resource", 1);
break;
}
}
default:
RETVAL_STRING("unknown type", 1);
}
}
为了验证gettype函数的底层实现,找到文件/ext/standard/type.c把gettype实现函数替换下玩玩:
PHP_FUNCTION(gettype)
{
zval **arg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
return;
}
switch (Z_TYPE_PP(arg)) {
case IS_NULL:
RETVAL_STRING("Bingo NULL", 1);
break;
case IS_BOOL:
RETVAL_STRING("Bingo boolean", 1);
break;
case IS_LONG:
RETVAL_STRING("Bingo integer", 1);
break;
case IS_DOUBLE:
RETVAL_STRING("Bingo double", 1);
break;
case IS_STRING:
RETVAL_STRING("Bingo string", 1);
break;
case IS_ARRAY:
RETVAL_STRING("Bingo array", 1);
break;
case IS_OBJECT:
RETVAL_STRING("Bingo object", 1);
/*
{
char *result;
int res_len;
res_len = sizeof("object of type ")-1 + Z_OBJCE_P(arg)->name_length;
spprintf(&result, 0, "object of type %s", Z_OBJCE_P(arg)->name);
RETVAL_STRINGL(result, res_len, 0);
}
*/
break;
case IS_RESOURCE:
{
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_LVAL_PP(arg) TSRMLS_CC);
if (type_name) {
RETVAL_STRING("resource", 1);
break;
}
}
default:
RETVAL_STRING("unknown type", 1);
}
}
按照引文4.3所述,下载php源码,配置,编译。这里–prefix填写编译后的目录路径前缀,譬如/home/users/yangding/php,最后执行make install安装,安装结果将放在/home/users/yangding/php目录下。
安装完成后,执行测试代码
/home/users/yangding/php/bin/php -r '$test =1;print_r(gettype($test));'
得到运行结果
Bingo integer