PHP extension и вызов php callback?

Привет


Я пишу тестовой модуль для 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/>
  • Вопрос задан
  • 3356 просмотров
Решения вопроса 1
AlexeyK
@AlexeyK
strace поможет
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы