Продолжаем разбирать расширения PHP на составляющие…
Сегодня мы поговорим о том, как возвращать некие значения из функций. В предыдущих статьях мы уже встречались с макросом RETURN_STRING (), сегодня мы узнаем о других макросах для возвращения результатов с типом, отличном от строки. А в частности, мы разберемся как вернуть из функции string, boolean, long, double, array.
Приступим
Для начала мы как всегда декларируем нужные нам функции:
PHP_FUNCTION(hello_string); PHP_FUNCTION(hello_long); PHP_FUNCTION(hello_double); PHP_FUNCTION(hello_bool); PHP_FUNCTION(hello_array); // list of custom PHP functions provided by this extension // set {NULL, NULL, NULL} as the last record to mark the end of list static zend_function_entry my_functions[] = { PHP_FE(hello_string, NULL) PHP_FE(hello_long, NULL) PHP_FE(hello_double, NULL) PHP_FE(hello_bool, NULL) PHP_FE(hello_array, NULL) {NULL, NULL, NULL} };
Что тут и как я думаю пояснять не стоит, ибо это было описано в прошлой и позапрошлой статье.
Следом же можно приступить к реализации функций.
Реализация
И как можно догадаться — реализация будет банальной, и сложного в ней ничего не будет. Приступим.
PHP_FUNCTION(hello_string) { RETURN_STRING("hello", 1); } PHP_FUNCTION(hello_long) { RETURN_LONG(100500); } PHP_FUNCTION(hello_double) { RETURN_DOUBLE(100.5); } PHP_FUNCTION(hello_bool) { RETURN_TRUE; }
С макросом RETURN_STRING мы познакомились в первой статье этой серии — он имеет два аргумента, строку которую вернуть, и вернуть ли ее копию, или ссылку на нее. Но как ни странно — вернуть по ссылке не получилось у меня строку — после завершения выполнения функции PHP выпадает с SEGFAULT.
С макросами RETURN_LONG (l) и RETURN_DOUBLE (d) все еще проще — они имеют по одному аргументу, и принимают в качестве аргументов значения типа long и double соотвественно.
Для возврата булевого значения — есть два макроса RETURN_TRUE и RETURN_FALSE, и они не имеют аргументов.
Есть еще возможность возвращать null — для этого есть макрос RETURN_NULL который так же не имеет аргументов.
Тут вы наверное спросите: «а где же обещанные массивы? ». Возвращение массивов немного отличается от возвращения значений с примитивными типами, и реализуется примерно так:
PHP_FUNCTION(hello_array) { array_init(return_value); add_assoc_string(return_value, "hello", "world", 1); }
Тут мы видим макрос array_init (arg) который инициализирует массив в переменной return_value (return_value — это указатель который передается в функцию и он указывает на zval значение которое будет возвращено функцией). Так же, видим макрос add_assic_string (arg, key, val, duplicate) который добавляет в ассоциативный массив строковое значение. Помимо add_assic_string () есть так же и другие макросы:
- add_assoc_long (arg, key, long) — добавляет значение типа long
- add_assoc_dobut (arg, key, double) — добавляет значение типа double
- add_assoc_bool (arg, key, bool) — добавляет булево значение
- add_assoc_null (arg, key) — добавляет null
- add_assoc_resource (arg, key, res) — добавляет ресурс
- add_assoc_stringl (arg, key, str, len, duplicate) — судя по всему, добавляет строку с указанием длины.
- add_assoc_zval (arg, key, val) — добавляет zval значение
Помимо всего прочего, есть аналогичные функции add_nex_index_*() для добавления значение я в индексированный массив.
Результат
После того как мы собрали и установили расширение с помощью make && sudo make install можно проверить результат работы наших функций. У меня получилось что‐то вроде следующего:
popsul@oo-pc:~/projects/php_ext$ /usr/bin/php -r 'var_dump(hello_string());' string(5) "hello" popsul@oo-pc:~/projects/php_ext$ /usr/bin/php -r 'var_dump(hello_long());' int(100500) popsul@oo-pc:~/projects/php_ext$ /usr/bin/php -r 'var_dump(hello_double());' double(100.5) popsul@oo-pc:~/projects/php_ext$ /usr/bin/php -r 'var_dump(hello_bool());' bool(true) popsul@oo-pc:~/projects/php_ext$ /usr/bin/php -r 'var_dump(hello_array());' array(1) { 'hello' => string(5) "world" }
Как видим, все прекрасно работает.
Примечания
Помимо перечисленных RETURN_* макросов, также есть RETURN_ZVAL (zv, copy, dtor) для возвращения значения с типом zval, а также RETURN_STRINGL (s, l, duplicate) для строки с указанием длины и RETURN_EMPTY_STRING () для возвращения пустой строки.
Заключение
Исходник получившегося можно взять тут => hello_world.c.
P.S. Подписывайтесь на RSS моего блога :)