| ||||||||||
Глава 39. Вызов пользовательских функцийВы можете вызывать пользовательские функции из ваших модулей, что очень удобно при реализации callbacks/обратных вызовов; например, для прохода по массиву, поиска или просто для программ на базе событий. Пользовательские функции можно вызывать функцией call_user_function_ex(). Необходимы: hash-значение для таблицы функции, доступ к которой вы хотите получить, указатель на объект (если хотите вызвать метод), имя функции, return-значение, количество аргументов, массив аргументов и флаг, указывающий, хотите ли вы использовать zval-сепарацию.
Заметьте, что вы не должны специфицировать и function_table, и object; нужен только один из них. Если вы хотите вызвать метод, вы должны предоставить объект, который содержит этот метод, при этом call_user_function() автоматически устанавливает таблицу функции на таблицу функции этого объекта. Иначе вам необходимо специфицировать только function_table и можно установить object в NULL. Обычно по умолчанию таблица функции это таблица "корневой" функции, содержащая вхождения всех функций. Эта таблица функции является частью глобалов компилятора, и доступ к ней может быть обеспечен макросом CG. Для введения глобалов компилятора в вашу функцию, вызовите однократно макрос CLS_FETCH. Имя функции специфицируется в zval-контейнере. На первый взгляд это может показаться необычным, но это довольно логичный шаг, поскольку в большинстве случаев вы будете принимать имена функций как параметры вызывающих функций в вашем скрипте, которые в свою очередь также содержаться в zval-контейнерах. Таким образом, вы должны лишь передать ваши аргументы этой функции. Этот zval обязан иметь тип IS_STRING. Следующий аргумент это указатель на return-значение. Вы не должны выделять память для этого контейнера; функция сделает это сама. Однако вы должны уничтожить этот контейнер (используя zval_dtor()) впоследствии! Затем идёт целочисленный parameter_count и массив, содержащий все необходимые параметры. Последний аргумент специфицирует, должна ли функция выполнять zval-сепарацию - он должен всегда быть установлен в 0. Если он установлен в 1, функция потребляет меньше памяти, но терпит неудачу, если любой из параметров требует сепарации. Листинг 9.16 и Рисунок 9.11 показывают вызов пользовательской функции. Этот код вызывает функцию, которая предоставлена как аргумент, и непосредственно передаёт return-значение этой функции как своё собственное return-значение. Обратите внимание на использование вызовов конструктора и деструктора в конце - это может быть и не обязательно здесь (так как они являются раздельными значениями, и присвоение проходит безопасно), но так 100-процентно надёжнее. Рисунок 39-1. Листинг 9.16. Вызов пользовательской функции.
| ||||||||||
|