Привет
Я пишу тестовой модуль для PHP
В нем есть класс Test1, у него есть метод addCallback а также событие на set (
handler set)
Метод addCallback:
PHP_METHOD(Test1, addCallback)
{
Test1_Extra *ExThis = (Test1_Extra*) zend_object_store_get_object(getThis() TSRMLS_CC);
// запоминаем callback
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", &(ExThis->callback), &(ExThis->callback_cache)) == FAILURE) {
return;
}
// здесь запускаем callback для теста
zend_fcall_info_call(&(ExThis->callback), &(ExThis->callback_cache), NULL, NULL TSRMLS_CC);
}
Object handler SET (вызывает callback):
void Test1_object_set(zval **pzobject, zval *value TSRMLS_DC)
{
Test1_Extra *ExThis = (Test1_Extra*) zend_object_store_get_object(*pzobject TSRMLS_CC);
zend_fcall_info_call(&(ExThis->callback), &(ExThis->callback_cache), NULL, NULL TSRMLS_CC);
}
PHP код:
<?php
function test_callback() {
echo 'run'.PHP_EOL;
}
$test = new Test1;
$test->addCallback('test_callback');
$test = 'dd'; // здесь срабатывает Test1_object_set
Результат выполнения:
run<br/>
Segmentation fault<br/>
Тоесть, как только мы получили callback, то сразу выполняется, но потом не получается.
Но самое интересно что если изменить функцию так (добавить ручной запуск php функции):
static void Test1_object_set(zval **pzobject, zval *value TSRMLS_DC)
{
Test1_Extra *ExThis = (Test1_Extra*) zend_object_store_get_object(*pzobject TSRMLS_CC);
zval *fname;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
MAKE_STD_ZVAL(fname);
ZVAL_STRINGL(fname, "test_callback", 3, 1);
zend_fcall_info_init(fname, 0, &fci, &fcc, NULL, NULL TSRMLS_CC);
// выполняем вручную функцию test_callback
zend_fcall_info_call(&fci, &fcc, NULL, NULL TSRMLS_CC);
zend_fcall_info_call(&(ExThis->callback), &(ExThis->callback_cache), NULL, NULL TSRMLS_CC);
}
То результат выполнения:
run<br/>
run<br/>
run<br/>
Тоесть, прошлый код заработал.
После некоторых исследований оказалось что код начинает работать после
zend_fcall_info_init(fname, 0, &fci, &fcc, NULL, NULL TSRMLS_CC);
Не как не могу понять почему так происходит, и как сделать правильно.
Спасибо.
UPD.
Определил что если в zend_fcall_info_init прописать другую функцию, то последующее
zend_fcall_info_call(&(ExThis->callback), &(ExThis->callback_cache), NULL, NULL TSRMLS_CC);
тоже почему то её вызывает
UPD 2.
Что то я совсем не понимаю.
zval *fname = ExThis->callback.function_name;
char *cfname = Z_STRVAL_P(fname);
php_printf("fname: %s\n", "test msg");
php_printf("fname: %s\n", cfname);
Результат
fname: test msg<br/>
Segmentation fault<br/>