Пишем расширение для PHP
Для чего может понадобиться написать свое расширение?
- Существенно повышается скорость исполнения кода
- Защита существующего кода — код поставляется в виде бинарника
- Работа с драйверами, «железом на прямую» или использование сторонних dll/so
При разработке данного мануала использовались ресурсы http://www.php-cpp.com и https://habr.com/post/98862/, а так-же ряд других.
- Попробуем на Ubuntu php 7.2
Скачиваем и шаблон для разработки расширения на cpp
1 2 3 |
git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.git cd PHP-CPP make |
Получаем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pavel@pavelpc:~/reserved/getcoding/phpcpp$ make mkdir -p shared/common mkdir -p shared/zend g++ -Wall -c -std=c++11 -fvisibility=hidden -DBUILDING_PHPCPP -Wno-write-strings -MD -g -fpic -o shared/common/streambuf.o common/streambuf.cpp g++ -Wall -c -std=c++11 -fvisibility=hidden -DBUILDING_PHPCPP -Wno-write-strings -MD -g -fpic -o shared/common/modifiers.o common/modifiers.cpp g++ -Wall -c -std=c++11 -fvisibility=hidden -DBUILDING_PHPCPP -Wno-write-strings -MD -g `php-config --includes` -fpic -o shared/zend/inivalue.o zend/inivalue.cpp /bin/sh: 1: php-config: not found In file included from zend/inivalue.cpp:8:0: zend/includes.h:40:10: fatal error: php.h: Нет такого файла или каталога #include <php.h> ^~~~~~~ compilation terminated. Makefile:204: recipe for target 'shared/zend/inivalue.o' failed make: *** [shared/zend/inivalue.o] Error 1 |
Не хватает исходных кодов php. Скачиваем, предварительно узнав текущую версию:
1 2 3 4 5 6 7 |
pavel@pavelpc:~/reserved/getcoding/phpcpp$ php --version PHP 7.2.7-0ubuntu0.18.04.2 (cli) (built: Jul 4 2018 16:55:24) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.2.7-0ubuntu0.18.04.2, Copyright (c) 1999-2018, by Zend Technologies pavel@pavelpc:~/reserved/getcoding/phpcpp$ sudo apt-get install php7.2-dev |
Снова пробуем make:
1 2 3 4 |
pavel@pavelpc:~/reserved/getcoding/phpcpp$ make ... Build complete. pavel@pavelpc:~/reserved/getcoding/phpcpp$ sudo make install |
В папке Examples лежит несколько примеров. Попробуем скомпилировать so на основе FunctionReturnValue:
1 2 3 |
pavel@pavelpc:~/reserved/getcoding/phpcpp/Examples/FunctionReturnValue$ make g++ -Wall -c -I. -O2 -std=c++11 -fpic -o functionreturnvalue.o functionreturnvalue.cpp g++ -Wall -shared -O2 -o functionreturnvalue.so functionreturnvalue.o -lphpcpp |
Подключим получившуюся библиотеку в php.ini:
1 2 3 |
pavel@pavelpc:~/reserved/getcoding/phpcpp/Examples/FunctionReturnValue$ php-config --extension-dir /usr/lib/php/20170718 pavel@pavelpc:~/reserved/getcoding/phpcpp/Examples/FunctionReturnValue$ sudo cp functionreturnvalue.so /usr/lib/php/20170718 |
В php.ini добавим строчку:
1 |
extension=/usr/lib/php/20170718/functionreturnvalue.so |
и выполним тестовый скрипт:
1 2 |
pavel@pavelpc:~/reserved/getcoding/phpcpp/Examples/FunctionReturnValue$ php -r 'echo my_return_value_function() . "\n";' 42 |
2. Теперь тоже самое на FreeBSD 10.3 и php 5.4
Сначала попробовал скопировать получившийся в Ubuntu so из Ubuntu на FreeBSD и подключить расширением. А вдруг заработает? Не заработало 😉
1 2 3 4 5 6 7 |
root@noc:/usr/local/etc/php # php --version PHP Warning: PHP Startup: Unable to load dynamic library '/usr/local/lib/php/20100525/functionreturnvalue.so' - Shared object "libphpcpp.so.2.1" not found, required by "functionreturnvalue.so" in Unknown on line 0 Warning: PHP Startup: Unable to load dynamic library '/usr/local/lib/php/20100525/functionreturnvalue.so' - Shared object "libphpcpp.so.2.1" not found, required by "functionreturnvalue.so" in Unknown on line 0 PHP 5.4.45 (cli) (built: Jan 31 2016 02:44:32) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies |
Тогда делаем всё тоже самое что и в п.1:
1 2 3 |
git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.git cd PHP-CPP make |
Ой:
1 2 3 4 5 6 7 8 9 10 11 12 |
root@noc:/home/pavel/PHP-CPP # make make: "/usr/home/pavel/PHP-CPP/Makefile" line 35: Missing dependency operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 37: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 39: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 78: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 81: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 84: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 86: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 88: Need an operator make: "/usr/home/pavel/PHP-CPP/Makefile" line 90: Need an operator make: Fatal errors encountered -- cannot continue make: stopped in /usr/home/pavel/PHP-CPP |
Установим g++:
1 |
pkg install lang/gcc49 |
Во FreeBSD g++ называется clang++, можно сделать символическую ссылку:
1 |
ln /usr/bin/clang++ /usr/bin/g++ |
Снова попробовав make, видим те-же ошибки… Ну чтож, сделаем тогда свой Makefile:
1 2 3 4 |
root@noc:/home/pavel/PHP-CPP # cmake /home/gavnetadmin/PHP-CPP -- Configuring done -- Generating done -- Build files have been written to: /home/gavnetadmin/PHP-CPP |
Снова пробуем:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
root@noc:/home/gavnetadmin/PHP-CPP # make [ 5%] Built target phpcpp-common [ 8%] Building CXX object CMakeFiles/phpcpp.dir/zend/base.cpp.o In file included from /home/gavnetadmin/PHP-CPP/zend/base.cpp:8: /home/gavnetadmin/PHP-CPP/zend/includes.h:40:10: fatal error: 'php.h' file not found #include <php.h> ^ 1 error generated. *** Error code 1 Stop. make[2]: stopped in /usr/home/gavnetadmin/PHP-CPP *** Error code 1 Stop. make[1]: stopped in /usr/home/gavnetadmin/PHP-CPP *** Error code 1 Stop. make: stopped in /usr/home/gavnetadmin/PHP-CPP |
Продолжение следует… Буду обновлять FreeBSD до актуальной версии и иставить php 7.