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

1 Answer 1

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);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.