A
A
Andrew2011-09-13 15:20:09
PHP
Andrew, 2011-09-13 15:20:09

PHP extension and php callback?

Hi
I am writing a test module for PHP
It has a class Test1 it has an addCallback method and also an event on set ( handler set )
addCallback method:

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 (calls 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 code:
<?php
    function test_callback() {
        echo 'run'.PHP_EOL;
    }

    $test = new Test1;
    $test->addCallback('test_callback');
    $test = 'dd'; // здесь срабатывает Test1_object_set

Execution result:
run<br/>
Segmentation fault<br/>

That is, as soon as we received a callback, it is immediately executed, but then it does not work.
But the most interesting thing is that if you change the function like this (add a manual launch of the php function):
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);
 }

That is the result of running:
run<br/>
 run<br/>
 run<br/>

That is, the previous code has earned.
After some research, it turned out that the code starts working after
zend_fcall_info_init(fname, 0, &fci, &fcc, NULL, NULL TSRMLS_CC);

I can't figure out why this is happening and how to do it right.
Thank you.
UPD.
I determined that if another function is written in zend_fcall_info_init, then the following
zend_fcall_info_call(&(ExThis->callback), &(ExThis->callback_cache), NULL, NULL TSRMLS_CC);

For some reason, it also causes
UPD 2.
Something I don’t understand at all.
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);

Result
fname: test msg<br/>
Segmentation fault<br/>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
AlexeyK, 2011-09-13
@Morfi

strace will help

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question