当我在PHP_FUNCTION里获得一个PHP对象的字符串,我希望在内存中直接生成PHP的对象,共下面代码调用。
类似PHP中的eval函数。
例如:
   $strClass = "class A {function test(){echo 'test';}}";
   eval($strClass);
把这段功能用php拓展 C或C++实现。

解决方案 »

  1.   

    本帖最后由 xuzuning 于 2012-11-26 17:04:58 编辑
      

  2.   

    eval是语言结构,在php.net的中文文档中并没有详细说明。但是英文文档写明了:The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
    在php的源码中找eval函数找不到
    源码文件:Zend/zend_language_parser.y
    -------------------------------
    internal_functions_in_yacc:
    T_ISSET '(' isset_variables ')' { $$ = $3; }
    | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); }
    | T_INCLUDE expr  { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); }
    | T_INCLUDE_ONCE expr  { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); }
    | T_EVAL '(' expr ')'  { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
    | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); }
    | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); }
    ;第6行那个
    T_EVAL '(' expr ')'  { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); }
    就是eval,在其他文件中定义了这个token就是eval。其中第一个参数,我找到了常量的定义:
    #define ZEND_EVAL (1<<0)
    #define ZEND_INCLUDE (1<<1)
    #define ZEND_INCLUDE_ONCE (1<<2)
    #define ZEND_REQUIRE (1<<3)
    #define ZEND_REQUIRE_ONCE (1<<4)
    ...
    比较有趣,它为什么要这样左移位来赋值?问了做c的同事,给了我一种解释,说是这样写比较简洁。如果要写一个1<<31的实际数太大了,容易出错。void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
    {
    zend_do_extended_fcall_begin(TSRMLS_C);
    {
    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_INCLUDE_OR_EVAL;
    opline->result_type = IS_VAR;
    opline->result.var = get_temporary_variable(CG(active_op_array));
    SET_NODE(opline->op1, op1);
    SET_UNUSED(opline->op2);
    opline->extended_value = type;
    GET_NODE(result, opline->result);
    }
    zend_do_extended_fcall_end(TSRMLS_C);
    }
    /* }}} */楼主继续追下去看看里面的调用逻辑,能否通过这个zend api实现你要的功能。
      

  3.   

    找到了 ZEND 有一个API函数 zond_eval_string