Как обновить параметры функции PHP для работы с новым Zend API?

Я работаю над расширением php, чтобы обновить его до PHP7, мой вопрос касается INTERNAL_FUNCTION_PARAMETERS. В предыдущей версии он определяется как:

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

а в новом движке Zend это определяется как:

INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value

У меня есть функция php, которая возвращает массив, и она выглядит так: `

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

Как мне получить аналогичные функциональные возможности без использования return_value_ptr? Должен ли я использовать #define RETURN_ARR(r)? Если да, то как это влияет на производительность?


person Genjutsu    schedule 08.12.2015    source источник


Ответы (1)


В PHP 7 большинство указателей на zval-ы (zval*) в PHP 5 стали простыми zval-структурами (zval) - вместо того, чтобы передавать указатели на распределенные в куче (emalloc) zval-ы, сами zval-ы копируются. Из-за этого, в некотором смысле, return_value является новым return_value_ptr, потому что везде на один уровень косвенности меньше.

Итак, чтобы пройти построчно:


Линия 1:

zval* myArray;

В PHP 7 вы не храните указатель на zval, вы помещаете его прямо в стек. Нет внешнего распределения. Поэтому первая строка вашей функции должна быть:

zval myArray;

Строка 2:

array_init(myArray);

array_init нужен указатель на zval (zval*), так что это должно быть:

array_init(&myArray);

Строка 4:

zval_ptr_dtor( &return_value );

Опять же, PHP 7 убирает здесь уровень косвенности. Просто сейчас было бы так:

zval_dtor(return_value);

Однако вам не нужна эта строка в PHP 7. zval не нуждается в освобождении памяти (на самом деле вы не можете освободить его), вы можете просто перезаписать его. Однако вам понадобится использовать zval_dtor();, если zval содержит указатель на строку, массив или какой-либо другой объект, размещенный в куче. Но в этом случае это просто ноль, поэтому вам не нужно его запускать. Продолжая:


Строка 5:

*return_value_ptr = myArray;

Теперь это должно быть:

*return_value = myArray;

Однако, хотя здесь вы можете напрямую перезаписать return_value, для этого рекомендуется использовать макрос ZVAL_COPY_VALUE:

ZVAL_COPY_VALUE(return_value, &myArray);

Еще лучше, вы можете использовать RETVAL_ZVAL, который является ярлыком для установки возвращаемого значения:

RETVAL_ZVAL(&myArray);

Я должен указать, что вам, вероятно, не нужен myArray zval в этом случае, так как вы можете сохранить массив непосредственно в return_value и избавить вас от необходимости копировать его позже. Еще одна вещь, которую следует иметь в виду, это то, что вы, вероятно, должны обрабатывать параметры. Если вы ничего не принимаете, zend_parse_parameters_none(); достаточно.

Я предлагаю прочитать руководство по обновлению phpng и руководство по обновлению внутренних компонентов.

person Andrea    schedule 08.12.2015
comment
Обычно вам не следует назначать необработанные zval'ы напрямую, поэтому строка 5 должна быть ZVAL_COPY_VALUE(return_value, &myArray);, а еще лучше RETVAL_ZVAL(&myArray);. - person bwoebi; 08.12.2015