| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Приложение E. Расширение PHPДобавление функций в PHPПрототип функцииВсе функции выглядят так:
Даже если ваша функция не принимает аргументов, вызывается она именно так. Аргументы функцииАргументы всегда имеют тип pval. Этот тип содержит объединение/union, которое содержит фактический тип аргумента. Так, если ваша функция принимает два аргумента, вы должны записать нечто такое в верхней части вашей функции:
Примечание: Аргументы могут передаваться по значению или по ссылке. В обоих случаях вы должны передать &(pval *) в getParameters. Если вы хотите проверить, передан n-ный параметр по ссылке или нет, вы можете использовать функцию ParameterPassedByReference(ht,n). Она возвратит 1 или 0. Если вы изменяете любой из переданных параметров, переданы ли они по ссылке или нет, вы можете начать работу с данным параметром, вызвав pval_destructor на нём, или, если это ARRAY, в который вы хотите добавить данные, вы можете использовать функции, аналогичные тем, которые находятся в internal_functions.h и манипулируют return_value как ARRAY. Также, если вы изменяете параметр на IS_STRING, не забудьте сначала присвоить новую estrdup()'ированную строку и размер строки и только после этого изменяйте тип на IS_STRING. Если вы изменяете строку параметра, который уже является IS_STRING или IS_ARRAY, вы должны сначала запустить на нём pval_destructor. Переменное количество аргументов функцииФункция может принимать переменное количество аргументов. Если ваша функция может принять 2 или 3 аргумента, используйте следующее: Использование аргументов функцииТип каждого аргумента хранится в поле (свойстве) типа pval. Этот тип может быть одним из следующих: Таблица E-1. Внутренние типы PHP
Если вы получаете аргумент одного типа и хотите использовать его как другой тип, или если вы просто хотите форсировать приведение аргумента к определённому типу, вы можете использовать одну из следующих функций конвертации типа:
Все эти функции выполняют конвертацию на месте/in-place. Они ничего не возвращают. Реальный аргумент хранится в union; членами являются:
Работа с памятью в функцияхЛюбая необходимая функции память должна быть выделена с помощью emalloc() или estrdup(). Это абстрактные функции работы с памятью, которые выглядят и работают как нормальные функции malloc() и strdup(). Память должна освобождаться с помощью efree(). В программе имеются два вида памяти: память, которая возвращается разборщику в переменной, и память, которая нужна вам для временного хранения в вашей внутренней функции. Если вы присваиваете строку переменной, возвращаемой разборщику, вы должны сначала выделить память с помощью emalloc() или estrdup(). Эта память НИКОГДА НЕ ДОЛЖНА освобождаться вами, если только вы позднее не переписываете в этой же функции первоначальное присвоение (хотя этот стиль программирования нельзя приветствовать). Для любого временного/постоянного выделения памяти, необходимой вам в функции/библиотеке, вы должны использовать три функции: emalloc(), estrdup() и efree(). Они ведут себя ТОЧНО ТАК ЖЕ, как и их функции-двойники. Всё что вы emalloc() или estrdup(), вы должны efree() в той или иной точке, если это не предполагается делать в конце программы; иначе это приведёт к утечке памяти. Фраза "Они ведут себя ТОЧНО ТАК ЖЕ, как и их функции-двойники" означает: если вы efree() то, что не было emalloc()'овано или estrdup()'овано, вы можете получить нарушение сегментации. Поэтому, пожалуйста, будьте бдительны и освобождайте всю выделенную память. Если вы компилируете с опцией "-DDEBUG", PHP будет выводить весь листинг памяти, выделенной с помощью emalloc() и estrdup(), но не освобождённой с помощью efree(), при запуске специфицированного скрипта. Установка переменных в Таблице СимволовИмеются несколько макросов, которые облегчают установку переменной в таблице символов:
Таблицы символов в PHP реализованы как хэш-таблицы. В любое данное время &symbol_table является указателем на 'главную/main' таблицу символов, а active_symbol_table указывает на текущую активную таблицу символов (они могут быть идентичны, как при старте, или разными, если вы находитесь внутри функции). В следующих примерах использована 'active_symbol_table'. Вы должны заменить её на &symbol_table, если хотите работать именно с 'main' таблицей символов. Также эта же функция может применяться к массивам, как разъясняется ниже.
Массивы в PHP реализованы с использованием тех же хэш-таблиц, что и в таблицах символов. Это значит, что две вышеприведённые функции могут также использоваться для проверки переменных в массивах. Если вы хотите определить новый массив в таблице символов, вы должны сделать следующее: Сначала может понадобиться проверка существования массива и соответствующего выхода через использование hash_exists() или hash_find(). Инициализируем массив:
Этот код объявляет новый массив $foo в активной таблице символов. Это пустой массив. Вот как добавить в него новые вхождения:
Если вы хотите изменить значение, вставленное в хэш, вы обязаны сначала запросить его из хэша. Чтобы избежать этой лишней работы, вы можете предоставить pval ** функции add хэша, и он будет обновлён pval *-адресом элемента, вставленного в хэш. Если это значение равно NULL (как во всех предыдущих примерах) - этот параметр игнорируется. hash_next_index_insert() использует примерно ту же логику, что и "$foo[] = bar;" в PHP 2.0. Если вы конструируете массив для возвращения из функции, вы можете инициализировать этот массив, выполнив следующее:
... а затем добавляя значения вспомогательными функциями:
Конечно, если добавление не выполняется сразу после инициализации массива, вам сначала нужно будет найти этот массив:
Заметьте, что hash_find получает указатель на указатель pval, а не указатель pval. Любая функция хэша возвращает SUCCESS или FAILURE (кроме hash_exists(), которая возвращает булево значение). Возвращение простых значенийИмеются несколько макросов для облегчения получения return-значений из функций. Все макросы RETURN_* устанавливают return-значение и возвращают его из функции:
Макросы RETVAL_* устанавливают, но не возвращают, return-значение.
Все вышеприведённые строковые макросы будут estrdup() передаваемый аргумент 's', поэтому вы можете безопасно освободить аргумент после вызова макроса или, альтернативно, использовать статически размещённую память. Если ваша функция возвращает булевы ответы success/error, всегда используйте RETURN_TRUE и RETURN_FALSE, соответственно. Возвращение сложных значенийВаша функция может также возвращать сложные типы данных, такие как объект/object или массив/array. Возвращение объекта:
Функции для заполнения объекта:
Возвращение массива:
Вот функции для заполнения массива:
Использование списка ресурсовPHP имеет стандартные способы работы с ресурсами различных типов. Это замена всех локальных связанных списков PHP 2.0. Доступны функции:
Обычно эти функции используются для SQL-драйверов, но могут также использоваться для чего угодно; например, для обслуживания дескрипторов файлов. Типичный листинг кода выглядит так:
Типы ресурсов должны быть зарегистрированы в php3_list.h, в enum list_entry_type. Кроме того, нужно добавить shutdown-код для любого вновь определённого типа ресурса в list.c's list_entry_destructor() (даже если вы ничего особенного при отключении/shutdown делать не хотите, вы обязаны добавить пустой case). Использование постоянной таблицы ресурсовВ PHP есть стандартный способ хранения постоянных ресурсов (т.е.
ресурсов, хранимых между вызовами). Первым эту возможность использовал
модуль MySQL, а затем mSQL, поэтому можно получить представление о том,
как нужно использовать постоянные ресурсы, просмотрев mysql.c. Вам нужно просмотреть функции:
Общая идея постоянных модулей такова:
Если вы просмотрите mysql.c, обратите внимание, что, за исключением более сложной функции connect, остальная часть модуля не изменилась. Точно такой же интерфейс имеется для списка регулярных ресурсов и для списка постоянных ресурсов, только 'list' заменено на 'plist':
Более вероятно, однако, что эти функции окажутся бесполезны при попытке реализовать постоянный модуль. Обычно бывает нужно использовать тот факт, что список постоянных ресурсов является в действительности хэш-таблицей. Например, в модулях MySQL/mSQL, когда есть вызов pconnect() (постоянное connect), функция строит строку вывода host/user/passwd, которая передаётся этой функции, и хэширует SQL-ссылку этой строкой как ключом/key. При следующем вызове pconnect() с теми же host/user/passwd, будет сгенерирован тот же key, и функция найдёт SQL-ссылку в постоянном списке. Пока документация отсутствует, вы должны просмотреть в mysql.c или в msql.c, как можно использовать возможности хэш-таблиц plist'ов. Одно важное замечание: ресурсы, входящие в список постоянных ресурсов
обязаны *НЕ* размещаться менеджером памяти PHP,
т.е. они НЕ должны создаваться с помощью emalloc(), estrdup(), etc. Если вы регистрируете ресурс, вводимый в постоянный список, вы должны добавить для него деструктор как в постоянный, так и в непостоянный списки. Деструктор в деструкторе непостоянного списка ничего делать не должен. Деструктор в деструкторе постоянного списка должен соответствующим образом освобождать ресурсы, полученные данным типом (память, SQL-ссылки etc). Как и с непостоянными ресурсами, вы *ОБЯЗАНЫ* добавить деструкторы каждому ресурсу, даже если он не требует уничтожения и деструктор может быть пустым. Запомните: поскольку emalloc() и компания не используются в сочетании с постоянным списком, вы обязаны не использовать здесь efree() вообще. Добавление директив конфигурации времени прогона/runtimeМногие свойства PHP могут конфигурироваться на этапе прогона программы. Эти директивы конфигурации могут появляться или в файле php3.ini, или - в случае с версией Apache-модуля - Apache .conf-файлах. Преимущество их присутствия в Apache .conf-файлах заключается в том, что они могут быть сконфигурированы на уровне директорий. Это означает, что одна директория может иметь одну safemodeexecdir, например, а другая директория - другую. Эта дробность конфигурации особенно необходима, когда сервер поддерживает наличие несколько виртуальных хостов. Вот шаги по добавлению новой директивы:
|