Начиная с версии 5.3.0 в PHP изменился механизм передачи аргументов в функцию по ссылке. Передача аргументов в функцию по ссылке объявлена устаревшей и более не поддерживается http://www.php.net/manual/en/migration53.deprecated.php.
Аргументы передаваемый по ссылке следует указывать в объявлении функции. Т.е. так писать уже нельзя:
<?php
function my_last_error($errcode, $err) {
// Что-то делаем
$errcode = 1005;
$err = 'Last error';
}
$errno = 0;
$error = NULL;
my_last_error(&$error, &$errno);
?>
Теперь нужно писать так:
<?php
function my_last_error(&$errcode, &$err) {
// Что-то делаем
$errcode = 1005;
$err = 'Last error';
}
$errno = 0;
$error = NULL;
my_last_error($error, $errno);
?>
Для того чтобы создать функцию, в расширении PHP
, принимающую аргументы по ссылке, первым делом нужно описать ее аргументы:
ZEND_BEGIN_ARG_INFO_EX( arginfo_my_last_error, 0, 0, 2 )
ZEND_ARG_INFO(1, errno)
ZEND_ARG_INFO(1, error)
ZEND_END_ARG_INFO()
Макросы ZEND_BEGIN_ARG_INFO_EX()
, ZEND_ARG_INFO()
и ZEND_END_ARG_INFO()
создают массив структур zend_arg_info
с информацией об аргументах функции. Каждый аргумент функции описывается отдельной структурой.
Объявление макросов
Данные макросы имеют следующие объявление в PHP
5.3.5:
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
static const zend_arg_info name[] = { \
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
#define ZEND_END_ARG_INFO() ;
Аргументы макроса ZEND_BEGIN_ARG_INFO_EX()
:
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)
name
— Уникальное название структурыpass_rest_by_reference
— Следует ли необязательные аргументы передавать по ссылке: 0 — нет, 1 — даreturn_reference
— Передается ли возвращаемое значение по ссылкеrequired_num_args
— Кол-во обязательных аргументов функции
Аргументы макроса ZEND_ARG_INFO()
:
ZEND_ARG_INFO(pass_by_ref, name)
pass_by_ref
— Передавать ли этот аргумент по ссылке: 0 — нет, 1 — даname
— Название аргумента.
Все аргументы необходимо перечислять в том же порядке в каком они будут передаваться в функцию и соответственно обязательные аргументы, кол-во которых задается в макросе ZEND_BEGIN_ARG_INFO_EX()
, перечисляются первыми.
На этапе препроцессинга макросы будут развернуты следующим образом:
static const zend_arg_info arginfo_my_last_error[] = {
{ NULL, 0, NULL, 0, 0, 0, 0, 0, 2 },
{ errno, 5, NULL, 0, 0, 0, 1, 0, 0 },
{ error, 5, NULL, 0, 0, 0, 1, 0, 0 },
};
Объявление структуры zend_arg_info
:
typedef struct _zend_arg_info {
const char *name;
zend_uint name_len;
const char *class_name;
zend_uint class_name_len;
zend_bool array_type_hint;
zend_bool allow_null;
zend_bool pass_by_reference;
zend_bool return_reference;
int required_num_args;
} zend_arg_info;
После того как аргументы функции описаны, создаем собственно саму функцию:
PHP_FUNCTION(my_last_error) {
zval *ref_errcode = NULL;
zval *ref_error = NULL;
if ( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "zz", &ref_error, &ref_errcode ) == FAILURE ) {
return;
}
zval_dtor(ref_errcode);
zval_dtor(ref_error);
ZVAL_LONG(ref_errcode, 1005 );
ZVAL_STRING(ref_error, "Last error", 1);
}
Регистрация функции:
const zend_function_entry my_functions[] = {
....
PHP_FE(my_last_error, arginfo_my_last_erro )
....
};
Пример использования:
<?php
$errno = 0;
$error = NULL;
my_last_error($error, $errno);
echo $error.' (errno: '.$errno.')'; // Last error (errno: 1005)
?>