0

I'm trying to create a PHP extension that has a class and one of the elements is supposed to be an array of strings. When I try to do it like I have below, when I uncomment my attempts to create and implement an array in test_init_test(), I get the error "PHP Fatal error: Internal zval's can't be arrays, objects or resources in Unknown on line 0".

I'm either not understanding on how to create arrays or I'm just not understanding the zend_declare_property functions. How am I supposed to do this?

#include "php.h"
#include "php_myextension.h"
#include "test.h"

zend_class_entry *test_ce_test;

static zend_function_entry test_methods[] = {
    PHP_ME(Test, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)

    {NULL, NULL, NULL}
};

void test_init_test(TSRMLS_D) {
    zend_class_entry ce;

    // zval *cachedirs_array = emalloc(sizeof(zval));
    // array_init(cachedirs_array);

    INIT_CLASS_ENTRY(ce, "Test", test_methods);
    test_ce_test = zend_register_internal_class(&ce TSRMLS_CC);

    zend_declare_property_string(test_ce_test, "arch", sizeof("arch"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
    // zend_declare_property(test_ce_test, "cachedirs", sizeof("cachedirs"), cachedirs_array, ZEND_ACC_PUBLIC TSRMLS_CC);
    // zend_declare_property(test_ce_test, "cachedirs", sizeof("cachedirs"), cachedirs_array, ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(test_ce_test, "dbpath", sizeof("dbpath"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(test_ce_test, "root", sizeof("root"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
}

PHP_METHOD(Test, __construct) {
    char *rootpath;
    char *dbpath;
    size_t rp, dp;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &rootpath, &rp, &dbpath, &dp) == FAILURE) {
        RETURN_NULL()
    }

    object_init_ex(return_value, test_ce_test);

    zend_update_property_stringl(test_ce_test, getThis(), "root", sizeof("root"), rootpath, rp TSRMLS_CC);
    zend_update_property_stringl(test_ce_test, getThis(), "dbpath", sizeof("dbpath"), dbpath, dp TSRMLS_CC);
}

1 Answer 1

1

You have to declare an empty zval then update it with an array in the constructor.

void test_init_test(TSRMLS_D) {
    zend_class_entry ce;

    zval *cd = (zval*)malloc(sizeof(zval)); /* empty zval */

    INIT_CLASS_ENTRY(ce, "Test", test_methods);
    test_ce_test = zend_register_internal_class(&ce TSRMLS_CC);

    zend_declare_property_string(test_ce_test, "arch", sizeof("arch"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property(test_ce_test, "cachedirs", sizeof("cachedirs"), cd, ZEND_ACC_PUBLIC TSRMLS_CC); /* declare with empty zval */
    zend_declare_property_string(test_ce_test, "dbpath", sizeof("dbpath"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
    zend_declare_property_string(test_ce_test, "root", sizeof("root"), "", ZEND_ACC_PUBLIC TSRMLS_CC);
}

PHP_METHOD(Test, __construct) {
    char *rootpath;
    char *dbpath;
    size_t rp, dp;

    /* create zval */
    zval cd;

    /* init array */
    array_init(&cd);

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &rootpath, &rp, &dbpath, &dp) == FAILURE) {
        RETURN_NULL()
    }

    object_init_ex(return_value, test_ce_test);

    /* update property with new array */
    zend_update_property(alpm_ce_handle, getThis(), "cachedirs", sizeof("cachedirs") - 1, &cd TSRMLS_CC);

    zend_update_property_stringl(test_ce_test, getThis(), "root", sizeof("root"), rootpath, rp TSRMLS_CC);
    zend_update_property_stringl(test_ce_test, getThis(), "dbpath", sizeof("dbpath"), dbpath, dp TSRMLS_CC);
}
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.