2

I am working on a php extension to upgrade it to PHP7, my question is about INTERNAL_FUNCTION_PARAMETERS. In the previous version it is defined as:

INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC

and in the new zend engine it is defined as:

INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value

I have php function which returns an array and it looks like this: `

PHP_FUNCTION( myFunc ){ zval* myArray;
   array_init(myArray);
   /////
   zval_ptr_dtor( &return_value );
   *return_value_ptr = myArray;
}

How should I get similar functionalities without hanvig the return_value_ptr? Should I use #define RETURN_ARR(r)?, If so how does this affect the performance?

Andrea
  • 19,134
  • 4
  • 43
  • 65
Genjutsu
  • 223
  • 2
  • 12

1 Answers1

8

In PHP 7, most pointers to zvals (zval*) in PHP 5 have become plain zval structs (zval) - instead of passing around pointers to heap-allocated (emalloc) zvals, zvals themselves are copied. Because of this, in a sense, return_value is the new return_value_ptr, because there's one less level of indirection everywhere.

So, to go through line-by-line:


Line 1:

zval* myArray;

In PHP 7, you don't hold a pointer to a zval, you put it directly on the stack. No external allocation. So the first line of your function should be instead:

zval myArray;

Line 2:

array_init(myArray);

array_init needs a pointer to a zval (zval*), so this should be:

array_init(&myArray);

Line 4:

zval_ptr_dtor( &return_value );

Again, PHP 7 removes a level of indirection here. It would just be this now:

zval_dtor(return_value);

However, you don't need this line in PHP 7. The zval doesn't need deallocating (in fact you can't deallocate it), you can simply overwrite it. You would need to use zval_dtor(); if the zval contained a pointer to a string, array, or some other heap-allocated object, though. But in this case it's just a null, so you don't need to run it. Carrying on:


Line 5:

*return_value_ptr = myArray;

This should now be:

*return_value = myArray;

However, while you can directly overwrite return_value here, it is recommended to use the ZVAL_COPY_VALUE macro for this:

ZVAL_COPY_VALUE(return_value, &myArray);

Even better, you could use RETVAL_ZVAL which is a shortcut for setting the return value:

RETVAL_ZVAL(&myArray);

I should point out that you probably don't need the myArray zval in this case, as you can store the array in the return_value directly and save you having to copy it later. Another thing to bear in mind is that you should probably handle parameters. If you don't take any, zend_parse_parameters_none(); is sufficient.

I suggest reading the phpng upgrading guide and the internals upgrading guide.

Andrea
  • 19,134
  • 4
  • 43
  • 65
  • You usually shouldn't assign raw zvals directly, so line 5 should be `ZVAL_COPY_VALUE(return_value, &myArray);`, or even better `RETVAL_ZVAL(&myArray);`. – bwoebi Dec 08 '15 at 02:18