Новые книги

В этой книге автор представляет собранные по крупицам приемы и способы работы со словом, предложением, текстом. Всем, кто осваивает профессию копирайтера, будет полезно проанализировать массу интересных примеров из практики отечественных (и не только) рекламистов: от слоганов крупных компаний до причудливых фраз маленьких фирм. Книга приучает четко выражать свои мысли, перечитывать, анализировать и адекватно оценивать придуманное. Для рекламистов, маркетологов, специалистов по связям с общественностью, всех тех, кто пишет рекламные тексты.
Instagram сегодня – самая популярная и удобная площадка, с помощью которой можно стать действительно знаменитым. Петр Плосков – Instagram-продюсер № 1 в России, занимающийся продвижением Дмитрия Маликова, Натальи Рудовой, Марии Миногаровой, Иды Галич, Ольги Медынич, Ники Вайпер и других знаменитостей с миллионными аудиториями. В своей книге Петр рассказывает обо всем, что необходимо знать, чтобы стать следующей звездой.

Вызов Пользовательских Функций

Учебник РНР
Назад Вперёд

Глава 39. Вызов пользовательских функций

Вы можете вызывать пользовательские функции из ваших модулей, что очень удобно при реализации callbacks/обратных вызовов; например, для прохода по массиву, поиска или просто для программ на базе событий.

Пользовательские функции можно вызывать функцией call_user_function_ex(). Необходимы: hash-значение для таблицы функции, доступ к которой вы хотите получить, указатель на объект (если хотите вызвать метод), имя функции, return-значение, количество аргументов, массив аргументов и флаг, указывающий, хотите ли вы использовать zval-сепарацию.

ZEND_API int call_user_function_ex(HashTable *function_table, zval *object,
                                   zval *function_name, zval **retval_ptr_ptr,
                                   int param_count, zval **params[],
                                   int no_separation);

Заметьте, что вы не должны специфицировать и 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. Вызов пользовательской функции.
zval **function_name;
zval *retval;

if((ZEND_NUM_ARGS() != 1) || (zend_get_parameters_ex(1, &function_name) != SUCCESS))
{
    WRONG_PARAM_COUNT;
}

if((*function_name)->type != IS_STRING)
{
    zend_error(E_ERROR, "Функция requires string argument");
}

CLS_FETCH();

if(call_user_function_ex(CG(function_table), NULL, *function_name, &retval, 0, NULL, 0) != SUCCESS)
{
    zend_error(E_ERROR, "Функция call failed");
}

zend_printf("We have %i as type<br>", retval->type);

*return_value = *retval;
zval_copy_ctor(return_value);
zval_ptr_dtor();
 
<?php

dl("call_userland.so");

function test_function()
{

    print("We are in the test function!<br>");

    return("hello");

}

$return_value = call_userland("test_function");

print("Return value: \"$return_value\"<br>");
?>


НазадОглавление Вперёд
Функции старта и остановаВверх Поддержка файла инициализации