# New extension; nested function calls failing

- Thread: https://externals.io/message/3878
- Original archive: https://news-web.php.net/php.internals/3878
- Started by Bob Glamm on 2003-08-13T15:49:57+00:00
- Messages: 2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #3878 — Bob Glamm — 2003-08-13T15:49:57+00:00

URL: https://externals.io/message/3878#3878

(Apologies if this is the wrong list or if the answer to this has
escaped my searches, but I'm at my wit's end at the moment).

I'm trying to get a libical binding going for PHP (v4.3.2, with plans to
port to 5.0 as soon as it works with v4.3.x).  At the moment,
this PHP code works:

  $x = icalcomponent_new_vcalendar();
  $y = icalcomponent_new_vevent();
  $x->add_component($y);

but this fails:

  $x = icalcomponent_new_vcalendar();
  $x->add_component(icalcomponent_new_vevent());

Both icalcomponent_new_vcalendar() and icalcomponent_new_vevent() return
icalcomponent classes from the extension.  Icalcomponent has one 
data member ("resource") holding an icalcomponent *, and a class entry
containing a list of functions (such as "add_component") that can be
used to manipulate the component.

I've attempted to debug this - in the failing case the vcalendar
component and the vevent component are created correctly, but when
icalcomponent_new_vevent() returns something happens so that add_component
isn't being found properly:

$ gdb ../../../sapi/cli/php core
GNU gdb 5.3
Core was generated by `../../../sapi/cli/php t1.php'.
Program terminated with signal 11, Segmentation fault.
#0  call_overloaded_function (T=0xa0dc624c, arg_count=1, 
    return_value=0x81d86b4)
    at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:966
966             ce = Z_OBJCE_P(T->EA.data.overloaded_element.object);
(gdb) where
#0  call_overloaded_function (T=0xa0dc624c, arg_count=1, 
    return_value=0x81d86b4)
    at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:966
#1  0x081492ea in execute (op_array=0x81d416c)
    at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:1672
#2  0x0813cbf8 in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /tmp/new_installation/php-4.3.2-devel/Zend/zend.c:869
#3  0x08117630 in php_execute_script (primary_file=0xbffff460)
    at /tmp/new_installation/php-4.3.2-devel/main/main.c:1671
#4  0x0814d986 in main (argc=2, argv=0xbffff4f4)
    at /tmp/new_installation/php-4.3.2-devel/sapi/cli/php_cli.c:806
#5  0x4010af64 in __libc_start_main (main=0x814d1d0 <main>, argc=2, 
    ubp_av=0x0, init=0x8066d68 <_init>, fini=0x1, rtld_fini=0x81d84a0, 
    stack_end=0x807e0b0) at ../sysdeps/generic/libc-start.c:144

(In the call_overloaded_function frame, the T parameter pointer is
invalid).

This is the relevant code that is being called in the extension; perhaps
somewhere I am not constructing/returning an icalcomponent class zval
properly?

static void
icalcomponent_new_return(zval *rv, icalcomponent *icc)
{
  zend_class_entry *ce, icalcomponent_entry;
  zval *res;
  int resid;
  
  INIT_CLASS_ENTRY(icalcomponent_entry, "icalcomponent", icalcomponenttype_functions);
  ce = zend_register_internal_class(&icalcomponent_entry TSRMLS_CC);
  object_init_ex(rv, ce);
  
  MAKE_STD_ZVAL(res);
  resid = ZEND_REGISTER_RESOURCE(res, icc, icalcomponent_resource_id);
  add_property_resource(rv, "resource", resid);
} 

static ZEND_FUNCTION(icalcomponent_new_vcalendar)
{
  if(ZEND_NUM_ARGS() != 0) WRONG_PARAM_COUNT;
  icalcomponent_new_return(return_value, icalcomponent_new_vcalendar());
}

static ZEND_FUNCTION(icalcomponent_new_vevent)
{
  if(ZEND_NUM_ARGS() != 0) WRONG_PARAM_COUNT;
  icalcomponent_new_return(return_value, icalcomponent_new_vevent());
}

static ZEND_NAMED_FUNCTION(zif_icalcomponent_add_component)
{
  zval **entry, *icc_obj;
  zend_class_entry icalcomponenttype_entry;
  icalcomponent *icc = NULL, *child = NULL;

  if(ZEND_NUM_ARGS() != 1) WRONG_PARAM_COUNT;
  INIT_CLASS_ENTRY(icalcomponenttype_entry, "icalcomponent", icalcomponenttype_functions);
  if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o",
                           &icc_obj) == FAILURE)
    return;

  if(zend_hash_find(HASH_OF(getThis()), "resource", sizeof("resource"), (void **)&entry) == SUCCESS && Z_TYPE_PP(entry) == IS_RESOURCE)
    ZEND_FETCH_RESOURCE(icc, icalcomponent *, entry, -1, ICALCOMPONENT_RESOURCE, icalcomponent_resource_id);

  if(!icc || !icalcomponent_isa_component(icc) || !icalcomponent_is_valid(icc))
    return;

  if(zend_hash_find(HASH_OF(icc_obj), "resource", sizeof("resource"), (void **)&entry) == SUCCESS && Z_TYPE_PP(entry) == IS_RESOURCE)
    ZEND_FETCH_RESOURCE(child, icalcomponent *, entry, -1, ICALCOMPONENT_RESOURCE, icalcomponent_resource_id);

  if(!child || !icalcomponent_isa_component(child) || !icalcomponent_is_valid(child))
    return;

  icalcomponent_add_component(icc, child);
}


Any help would be appreciated.  Thanks in advance.

-Bob

---

## #3881 — Bob Glamm — 2003-08-13T17:43:44+00:00

URL: https://externals.io/message/3878#3881 · In reply to: #3878

Please disregard this, I found the problem - namely,
zend_register_internal_class should be called once on module
initialization per internal class, not once per class instantiation.

-Bob

> I'm trying to get a libical binding going for PHP (v4.3.2, with plans to
> port to 5.0 as soon as it works with v4.3.x).  At the moment,
> this PHP code works:
> 
>   $x = icalcomponent_new_vcalendar();
>   $y = icalcomponent_new_vevent();
>   $x->add_component($y);
> 
> but this fails:
> 
>   $x = icalcomponent_new_vcalendar();
>   $x->add_component(icalcomponent_new_vevent());
> 
> Both icalcomponent_new_vcalendar() and icalcomponent_new_vevent() return
> icalcomponent classes from the extension.  Icalcomponent has one 
> data member ("resource") holding an icalcomponent *, and a class entry
> containing a list of functions (such as "add_component") that can be
> used to manipulate the component.
> 
> I've attempted to debug this - in the failing case the vcalendar
> component and the vevent component are created correctly, but when
> icalcomponent_new_vevent() returns something happens so that add_component
> isn't being found properly:
> 
> $ gdb ../../../sapi/cli/php core
> GNU gdb 5.3
> Core was generated by `../../../sapi/cli/php t1.php'.
> Program terminated with signal 11, Segmentation fault.
> #0  call_overloaded_function (T=0xa0dc624c, arg_count=1, 
>     return_value=0x81d86b4)
>     at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:966
> 966             ce = Z_OBJCE_P(T->EA.data.overloaded_element.object);
> (gdb) where
> #0  call_overloaded_function (T=0xa0dc624c, arg_count=1, 
>     return_value=0x81d86b4)
>     at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:966
> #1  0x081492ea in execute (op_array=0x81d416c)
>     at /tmp/new_installation/php-4.3.2-devel/Zend/zend_execute.c:1672
> #2  0x0813cbf8 in zend_execute_scripts (type=8, retval=0x0, file_count=3)
>     at /tmp/new_installation/php-4.3.2-devel/Zend/zend.c:869
> #3  0x08117630 in php_execute_script (primary_file=0xbffff460)
>     at /tmp/new_installation/php-4.3.2-devel/main/main.c:1671
> #4  0x0814d986 in main (argc=2, argv=0xbffff4f4)
>     at /tmp/new_installation/php-4.3.2-devel/sapi/cli/php_cli.c:806
> #5  0x4010af64 in __libc_start_main (main=0x814d1d0 <main>, argc=2, 
>     ubp_av=0x0, init=0x8066d68 <_init>, fini=0x1, rtld_fini=0x81d84a0, 
>     stack_end=0x807e0b0) at ../sysdeps/generic/libc-start.c:144
> 
> (In the call_overloaded_function frame, the T parameter pointer is
> invalid).
> 
> This is the relevant code that is being called in the extension; perhaps
> somewhere I am not constructing/returning an icalcomponent class zval
> properly?
> 
> static void
> icalcomponent_new_return(zval *rv, icalcomponent *icc)
> {
>   zend_class_entry *ce, icalcomponent_entry;
>   zval *res;
>   int resid;
>   
>   INIT_CLASS_ENTRY(icalcomponent_entry, "icalcomponent", icalcomponenttype_functions);
>   ce = zend_register_internal_class(&icalcomponent_entry TSRMLS_CC);
>   object_init_ex(rv, ce);
>   
>   MAKE_STD_ZVAL(res);
>   resid = ZEND_REGISTER_RESOURCE(res, icc, icalcomponent_resource_id);
>   add_property_resource(rv, "resource", resid);
> } 
> 
> static ZEND_FUNCTION(icalcomponent_new_vcalendar)
> {
>   if(ZEND_NUM_ARGS() != 0) WRONG_PARAM_COUNT;
>   icalcomponent_new_return(return_value, icalcomponent_new_vcalendar());
> }
> 
> static ZEND_FUNCTION(icalcomponent_new_vevent)
> {
>   if(ZEND_NUM_ARGS() != 0) WRONG_PARAM_COUNT;
>   icalcomponent_new_return(return_value, icalcomponent_new_vevent());
> }
> 
> static ZEND_NAMED_FUNCTION(zif_icalcomponent_add_component)
> {
>   zval **entry, *icc_obj;
>   zend_class_entry icalcomponenttype_entry;
>   icalcomponent *icc = NULL, *child = NULL;
> 
>   if(ZEND_NUM_ARGS() != 1) WRONG_PARAM_COUNT;
>   INIT_CLASS_ENTRY(icalcomponenttype_entry, "icalcomponent", icalcomponenttype_functions);
>   if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o",
>                            &icc_obj) == FAILURE)
>     return;
> 
>   if(zend_hash_find(HASH_OF(getThis()), "resource", sizeof("resource"), (void **)&entry) == SUCCESS && Z_TYPE_PP(entry) == IS_RESOURCE)
>     ZEND_FETCH_RESOURCE(icc, icalcomponent *, entry, -1, ICALCOMPONENT_RESOURCE, icalcomponent_resource_id);
> 
>   if(!icc || !icalcomponent_isa_component(icc) || !icalcomponent_is_valid(icc))
>     return;
> 
>   if(zend_hash_find(HASH_OF(icc_obj), "resource", sizeof("resource"), (void **)&entry) == SUCCESS && Z_TYPE_PP(entry) == IS_RESOURCE)
>     ZEND_FETCH_RESOURCE(child, icalcomponent *, entry, -1, ICALCOMPONENT_RESOURCE, icalcomponent_resource_id);
> 
>   if(!child || !icalcomponent_isa_component(child) || !icalcomponent_is_valid(child))
>     return;
> 
>   icalcomponent_add_component(icc, child);
> }
> 
> 
> Any help would be appreciated.  Thanks in advance.
> 
> -Bob
> 
> -- 
> 
> 
> 
> 
> 
> <!DSPAM:3f3a5e2f204661244910416
