Разработка расширений php: возвращаемые значения

Продолжаем разбирать расширения 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 моего блога :)

comments powered by Disqus