Расширения Php: Некоторые Интересные Особенности

Вам не придется часто писать расширения для PHP на C++, но когда вы это сделаете, вы обнаружите, что публикаций и документации по этой теме не так уж и много.

Особенно если копнуть глубже.

Опишу несколько интересных моментов, которые мне пришлось выяснить «на собственном горьком опыте».

Неожиданные трудности нас ждут при вызове PHP-функций из кода расширения (который, напомню, мы пишем на C++).

Для этого предусмотрена функция call_user_function_ex, пример использования который не так сложно найти; Проблемы возникают, если удалить его вызов из функции C++, вызываемой из PHP. Такие функции объявляются следующим образом:

  
  
  
  
   

ZEND_FUNCTION(MyFunction) { … }

После перемещения call_user_function_ex за его пределы наше расширение перестает компилироваться.

Разгадка (и решение проблемы), конечно же, кроется в определении макроса ZEND_FUNCTION, который добавляет в определение функции пару параметров.

У нас нет другого выбора, кроме как передать их функции, откуда мы хотим получить доступ к PHP. Это будет выглядеть так:

ZEND_FUNCTION(MyFunction) { .

char *result = myInnerFunction ( CG ( function_table ), tsrm_ls ); .

} char *myInnerFunction ( HashTable *function_table, void ***tsrm_ls ) { .

call_user_function_ex(.

); .

}

Еще одна интересная особенность работы со структурами PHP из C++ связана с инструментами, которые предоставили нам разработчики PHP для работы с ассоциативными массивами.

В PHP мы привыкли легко работать с такими массивами и создавать многоэтажные структуры.

В C++ работа с ними превратится в кошмар: соответствующие API-методы, конечно, предусмотрены, но слишком удобными их назвать сложно.

Например, цикл, проходящий через один уровень массива, будет выглядеть так:

for (zend_hash_internal_pointer_reset_ex (arr_hash, &pointer); zend_hash_get_current_data_ex (arr_hash, (void**) &data, &pointer ) == SUCCESS; zend_hash_move_forward_ex (arr_hash, &pointer)) { .

}

Если в C++ вам нужно работать с многоэтажным массивом, то, честно говоря, с помощью этих инструментов вы с этим не справитесь.

Что вы можете предложить взамен? Достаточно простой и понятный вариант — разложить многоэтажный ассоциативный массив на два простых двумерных.

Один из них будет содержать «упакованные» ключи, второй — значения.

Вы можете упаковать ключи в строки, где ключи разных уровней будут разделены каким-либо символом.

Давайте представим себе такой массив в PHP:

$a = Array ( "user" => Array ( Array ( "name" => "Ivanov", "age" => 28), Array ( "name" => "Petrov", "age" => 23) ) );

В C++ в нем можно быстро найти значения, если упаковать его так:

string keys[] = { "user_0_name", "user_0_age", "user_1_name", "user_1_age" }; string values[] = { "Ivanov", "28", "Petrov", "23" };

Теги: #php #C++ #php #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.