这里阅读的php版本为PHP-7.1.0 RC3,阅读代码的平台为linuxphp
回到以前看的zend_eval_stringllinux
ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */ { ... new_op_array = zend_compile_string(&pv, string_name); // 这个是把php代码编译成为opcode的过程 ... zend_execute(new_op_array, &local_retval); // 这个是具体的执行过程,执行opcode,把结果存储到local_retval中 ... retval = SUCCESS; return retval; }
这里的zend_execute执行了两步,第一步是把php编译解析成为opcode的过程,咱们就先看这个。函数
zend_compile_string函数追下去能够追到compile_stringrest
// 将一个字符串解析成为op_array zend_op_array *compile_string(zval *source_string, char *filename) { zend_lex_state original_lex_state; zend_op_array *op_array = NULL; zval tmp; // 若是传进来要解析的字符为空,则返回null if (Z_STRLEN_P(source_string)==0) { return NULL; } ZVAL_DUP(&tmp, source_string); // 复制source_string到zval中 convert_to_string(&tmp); // 若是不是字符类型就转换为字符类型 source_string = &tmp; zend_save_lexical_state(&original_lex_state); // 保存lex上下文 if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) { // 作编译前的准备 BEGIN(ST_IN_SCRIPTING); // 设置状态为正在编译 op_array = zend_compile(ZEND_EVAL_CODE); // 进行编译,并把生成结果放在op_array中 } zend_restore_lexical_state(&original_lex_state); // 恢复lex上下文 zval_dtor(&tmp); // 释放tmp return op_array; }
里面最核心的就是zend_compile了。这里的几个点能够看看:code
1 这么作类型转换,参考convert_to_string。这个函数就是把任意类型的值转换为zval的string类型。
2 zval_dtor,这个函数是能把任意的zval变量作回收。很是好用。
3 ZVAL_DUP,是进行复制,它和ZVAL_COPY的区别在因而否增长gc的引用计数。字符串
下面又找到关键点:zend_compilestring