0

i am trying to warp a C library around a PHP class using PHP's Zend Engine. The constructor function of the class is supposed to take a string and a function pointer. I was able to fetch strings values from the __construct arguments and printing them. However when i fetch the function and try to make it run in the class's constructor. I get a segfault error.

Basically, the end result should like like so:

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

(Naturally, there are other methods in the class, but i had no issue with them). The C extension looks like so:

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);
}

Segfault doesn't happen when zend_call_function is commented out. I am using 7.2.19 and C99. Is there a way to solve this issue?

Thanks

Tim Fountain
  • 33,093
  • 5
  • 41
  • 69
AKJ
  • 950
  • 2
  • 13
  • 18

1 Answers1

0

You have to specify a zval for the return value of the function before you can call it. You also have to specify the number of parameters you want to pass:

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

To use parameters you have to allocate an array (stack or heap) of zvals to hold the values you want to pass. A simple example would be like this:

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]);

In case of heap allocation:

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