Создание Переменных
| ||||||||||
|
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(); } |
| ||||||
|
Нет комментариев. Ваш будет первым!