|
- Содержание
- Обзор
- Longs (Integers)
- Doubles (Floats)
- Строки
- Булевы
- Массивы
- Объекты
- Ресурсы
- Макросы для автоматического создания глобальных переменных
- Создание констант
При обмене данными вашего собственного расширения с PHP-скриптами одним из
самых важных вопросов является создание переменных. В это разделе показано,
как работать с типами переменных, поддерживаемых PHP.
Для создания новых переменных, видимых "извне" при выполнении скрипта, вам
необходимо выделить новый zval-контейнер,
заполнить его значениями и ввести его во внутреннюю таблицу символов Zend.
Базовый процесс - общий при создании всех переменных:
zval *new_variable;
/* разместить и инициализировать новый контейнер */
MAKE_STD_ZVAL(new_variable);
/* установить здесь тип и содержимое переменной, см. последующие разделы */
/* ввести эту переменную с именем "new_variable_name" в таблицу символов */
ZEND_SET_SYMBOL(EG(active_symbol_table), "new_variable_name", new_variable);
/* теперь переменная доступна скрипту как $new_variable_name */ |
Макрос MAKE_STD_ZVAL размещает новый zval-контейнер через использование
ALLOC_ZVAL и инициализирует его с помощьюINIT_ZVAL. В соответствии с реализацией Zend на момент написания, инициализация
означает установку счётчика ссылок на 1 и очистку флага is_ref, но этот процесс может быть в дальнейшем расширен - поэтому хорошо было бы
сохранить использование MAKE_STD_ZVAL вместо ALLOC_ZVAL. Если вы хотите оптимизировать скорость работы
(и не должны явным образом инициализировать здесь zval-контейнер), вы можете использовать
ALLOC_ZVAL, но это не рекомендуется, так как не гарантирует целостности данных.
ZEND_SET_SYMBOL заботится о внесении новой переменной в таблицу символов Zend. Этот макрос
проверяет, существует ли уже это значение таблице символов и конвертирует
новый символ в ссылку, если это так (с автоматическим уничтожением старого
zval-контейнера). Это предпочтительный метод, если скорость не является критичной и
вы хотели бы ограничить размер используемой памяти.
Обратите внимание, что ZEND_SET_SYMBOL использует глобалы Zend-исполнителя/executor через макрос
EG. Специфицируя EG(active_symbol_table), вы получаете доступ к текущей активной таблице символов, работая с активной
локальной областью видимости. Локальная область видимости может быть
разной, в зависимости от того, была ли функция вызвана из другой функции.
Если вам необходимо оптимизировать на скорость и вы не позаботитесь об
оптимальном использовании памяти, вы можете пропустить проверку на
существование переменной с тем же значением и форсировать вместо этого
вставку в таблицу символов через с использованием zend_hash_update():
zval *new_variable;
/* разместить и инициализировать новый контейнер */
MAKE_STD_ZVAL(new_variable);
/* установить здесь тип и содержимое переменной, см. последующие разделы */
/* ввести эту переменную с именем "new_variable_name" в таблицу символов */
zend_hash_update(
EG(active_symbol_table),
"new_variable_name",
strlen("new_variable_name") + 1,
&new_variable,
sizeof(zval *),
NULL
); |
Это стандартный метод, используемый в большинстве модулей.
Переменные, сгенерированные вышеприведённым кодом, всегда будут иметь локальную
область видимости, так что они находятся в контексте, в котором функция была вызвана.
Для создания новой переменной с глобальной областью видимости используйте
тот же самый метод, но обращайтесь к другой таблице символов:
zval *new_variable;
// разместить и инициализировать новый контейнер
MAKE_STD_ZVAL(new_variable);
//
// установить здесь тип и содержимое переменной
//
// ввести эту переменную с именем "new_variable_name" в таблицу символов
ZEND_SET_SYMBOL(&EG(symbol_table), "new_variable_name", new_variable); |
Макрос ZEND_SET_SYMBOL теперь вызван со ссылкой на главную, глобальную таблицу символов по ссылке
EG(symbol_table).
- Примечание: переменная active_symbol_table это указатель, а symbol_table
- не указатель. По этой причине вы должны использовать EG(active_symbol_table) и
&EG(symbol_table) как параметры для ZEND_SET_SYMBOL - он требует указателя.
Аналогично для получения более эффективно работающей версии вы можете жёстко
кодировать обновление таблицы символов:
zval *new_variable;
// разместить и инициализировать новый контейнер
MAKE_STD_ZVAL(new_variable);
//
// установить здесь тип и содержимое переменной
//
// ввести эту переменную с именем "new_variable_name" в глобальную таблицу символов
zend_hash_update(
&EG(symbol_table),
"new_variable_name",
strlen("new_variable_name") + 1,
&new_variable,
sizeof(zval *),
NULL
); |
В Листинге 9.10 показан пример исходного кода, создающего две переменные - local_variable
с локальной видимостью и global_variable с глобальной видимостью (см. Рисунок 9.7). Полный пример находится на CD-ROM.
- Примечание: вы увидите, что глобальная переменная теперь
недоступна из функции. Это потому, что она не импортирована в локальную
область видимости с использованием global $global_variable; в PHP-исходнике.
Рисунок 34-1. Листинг 9.10. Создание переменных с различными областями видимости.
ZEND_FUNCTION(variable_creation)
{
zval *new_var1, *new_var2;
MAKE_STD_ZVAL(new_var1);
MAKE_STD_ZVAL(new_var2);
ZVAL_LONG(new_var1, 10);
ZVAL_LONG(new_var2, 5);
ZEND_SET_SYMBOL(EG(active_symbol_table), "local_variable", new_var1);
ZEND_SET_SYMBOL(&EG(symbol_table), "global_variable", new_var2);
RETURN_NULL();
} |
| |