最近弄了一下PHP实现的源代码,先从CLI(Command Line Interface,非MS的Common Language Interface哦)入手的。笔记有点零散,不过从这些关键字搜索源代码,然后看看上下文也是有好处的。
zend_object_handle
/* {{{ proto DateTime::__construct([string time[, DateTimeZone object]])
Creates new DateTime object
*/
PHP_METHOD(DateTime, __construct)
zend_parse_parameters//分析参数
ZEND_NUM_ARGS()是传入的参数个数
zend_get_parameters_ex应该是获得参数的方法
//填入 return_value 即可成为函数返回值
STD_PHP_INI_ENTRY("date.timezone", "", PHP_INI_ALL, OnUpdateString, default_timezone, zend_date_globals, date_globals)不知道用来做什么的。
搜了好一阵子,
STD_PHP_INI_ENTRY("mysqli.default_port","3306", PHP_INI_ALL,OnUpdateLong,default_port,zend_mysqli_globals,mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_socket",NULL,PHP_INI_ALL,OnUpdateStringUnempty,default_socket,zend_mysqli_globals,mysqli_globals)
好像是配置可以指定的全局变量
date的object的定义
struct _php_date_obj {
zend_object std;
timelib_time *time;
};
应该是一种overlap的对象定义方法,看到
#define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL)
更坚定了这个看法
PHP_GINIT_FUNCTION又不知道用来做什么的,想删掉、设为空,可是好像是初始化的,不能删
PHP_GINIT(date), /* globals ctor */不知道ctor是什么意思,还有一个dtor也无从下手
//不过看到代码
static PHP_GINIT_FUNCTION(date)
{
date_globals->default_timezone = NULL;
date_globals->timezone = NULL;
}
是给全局配置变量用的,以后再说吧。
这里是定义类里的静态常数的
#define REGISTER_DATE_CLASS_CONST_STRING(const_name, value) \
zend_declare_class_constant_stringl(date_ce_date, const_name, sizeof(const_name)-1, value, sizeof(value)-1 TSRMLS_CC);
REGISTER_DATE_CLASS_CONST_STRING("ATOM", DATE_FORMAT_RFC3339);
PHP的值模型
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount;
zend_uchar type; /* active type */
zend_uchar is_ref;
};
cfg_get_long获得配置变量
object_init(return_value);初始化返回值
add_property_string(return_value, "name",result->fields[field_offset].name, 1);给返回值赋予属性
RETURN_ZVAL((zval *)data->php_value,1,0);生成zval的返回值
cli_sapi_module是命令行模块
参考php_reflection.c可以获得更多调用信息,参考com_dotnet可以更加了解php externtion的工作原理。
ZEND_METHOD(reflection_function, __construct)中zend_hash_find可以发现函数
如何hold住输出?
php_cli.c中的sapi_cli_ub_write可以hold输出
php_execute_simple_script应该可以简单执行,即不需要<?php ... ?>,后来证实并非如此,还是需要<?php ... ?>,不知道与zend_execute_scripts有什么区别。也没有文档说明一下,真是郁闷,难道源代码只是花瓶摆设?
登记变量
zend_declare_property_string
php_register_variable_ex
symtable1 = Z_ARRVAL_P(track_vars_array);
zend_get_parameters_array_ex获 得参数数组,从com_handlers.c中的static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)可以参照用法,可以参照 PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC) 的翻译不同系统的值的方法。反之则用PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC)。
PHP类型
/* data types */
/* All data types <= IS_BOOL have their constructor/destructors skipped */
#define IS_NULL 0
#define IS_LONG 1
#define IS_DOUBLE 2
#define IS_BOOL 3
#define IS_ARRAY 4
#define IS_OBJECT 5
#define IS_STRING 6
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
ZVAL_ADDREF增加引用,让系统不要在调用函数完毕后删除
zend_hash_internal_pointer_reset_ex重置循环
zend_hash_get_current_key_ex(Z_OBJPROP_P(z),...获得属性
zend_hash_move_forward_ex(Z_OBJPROP_P(z), &pos);循环下一个
zend_hash_get_current_key_ex(Z_OBJCE_P(z),...获得函数
这样以来就可以轮训所有的函数和属性了。
Main函数中的file_handle.handle.stream.reader是php代码输入,可以改造成流,默认的是文件,只要file_handle.handle.stream.reader=你的输入函数;即可。
另外一个值得一提的是,tsrm_ls
(它有多种define,TSRMLS_D,TSRMLS_DC,TSRMLS_C,TSRMLS_CC)
,这个变量贯穿几乎所有角落,它的创建只是轻描淡写tsrm_ls = ts_resource(0);不过,他是线程安全(Thread Security)的结构所在,还是一个难以理解的void ***,三重指针!
好啦,希望这些碎片对于完全不了解的人来说有点帮助吧。