Вам не придется часто писать расширения для PHP на C++, но когда вы это сделаете, вы обнаружите, что публикаций и документации по этой теме не так уж и много.
Особенно если копнуть глубже.
Опишу несколько интересных моментов, которые мне пришлось выяснить «на собственном горьком опыте».
Неожиданные трудности нас ждут при вызове PHP-функций из кода расширения (который, напомню, мы пишем на C++).
Для этого предусмотрена функция call_user_function_ex, пример использования который не так сложно найти; Проблемы возникают, если удалить его вызов из функции C++, вызываемой из PHP. Такие функции объявляются следующим образом:
После перемещения call_user_function_ex за его пределы наше расширение перестает компилироваться.ZEND_FUNCTION(MyFunction) { … }
Разгадка (и решение проблемы), конечно же, кроется в определении макроса 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++
-
Синтетический Мониторинг Производительности
19 Oct, 24 -
Тестирование В Mail.ru Group
19 Oct, 24 -
Связь-Экспокомм 2012
19 Oct, 24 -
Pinterest Добавит Кнопку «Купить»
19 Oct, 24 -
Red Alert 3 Бета
19 Oct, 24