【问题标题】:Segfault Error when using zend_call_function()使用 zend_call_function() 时的段错误
【发布时间】:2020-01-28 06:37:48
【问题描述】:

我正在尝试使用 PHP 的 Zend 引擎围绕 PHP 类扭曲 C 库。类的构造函数应该接受一个字符串和一个函数指针。我能够从 __construct 参数中获取字符串值并打印它们。但是,当我获取该函数并尝试使其在类的构造函数中运行时。我收到一个段错误。

基本上,最终结果应该是这样的:

class TestClass
{
   function __construct(callable: $callBack, string: $name);
}

(当然,类中还有其他方法,但我对它们没有意见)。 C 扩展名如下所示:

PHP_METHOD(TestClass, __construct)
{
    zend_string* name;
    zend_fcall_info fci;
    zend_fcall_info_cache fci_cache;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "fS", &fci, &fci_cache, &name) == FAILURE)
        return;
    php_printf("name: %s\n", ZSTR_VAL(name));
    if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS) {
        php_printf("Called");
    }
    zval* obj = getThis();
    test_class_t* intern;
    intern = Z_TSTOBJ_P(obj);
    php_printf("Constructor\n");
    zend_string_release(name);
    if (fci.params)
        efree(fci.params);
}

zend_call_function 被注释掉时不会发生段错误。 我正在使用 7.2.19 和 C99。 有没有办法解决这个问题?

谢谢

【问题讨论】:

    标签: php c php-internals


    【解决方案1】:

    在调用函数之前,你必须为函数的返回值指定一个 zval。您还必须指定要传递的参数数量:

    zval retval;
    fci.retval = &retval;
    fci.param_count = 0;
    // Use zend_call_function()
    zval_ptr_dtor(&retval);
    

    要使用参数,您必须分配一个 zval 数组(堆栈或堆)来保存您要传递的值。一个简单的例子是这样的:

    zval args[2];
    ZVAL_LONG(&args[0], 1);
    ZVAL_LONG(&args[1], 2);
    fci.params = args;
    fci.param_count = 2;
    // Use zend_call_function() here.
    zval_ptr_dtor(&args[0]);
    zval_ptr_dtor(&args[1]);
    

    在堆分配的情况下:

    zval *args = emalloc(2 * sizeof(zval));
    // Assign, call and dtor as in previous example.
    efree(args);
    

    【讨论】:

      猜你喜欢
      • 2017-08-02
      • 2010-10-07
      • 2021-07-03
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-25
      相关资源
      最近更新 更多