How To - Eigene Module für PHP mit C++ schreiben
mastercad
30.07.2017 11:43:15
Das ist nur eine kurze Zusammenfassung, um den Ablauf zu skizzieren, es soll noch ein umfangreicheres Tutorial folgen, in naher Zukunft.
Zu erst installieren wir die php development files:
[code lang=bash]
sudo apt-get install php-dev
zusätzlich für php 5.x:
sudo apt-get install php5-dev
oder für php 7.x
sudo apt-get install php7.0-dev
[/code]
Danach laden wir uns PHPCpp herunter unter PHPCpp auf Github.
dann gehen wir in das verzeichnis, erstellen die binaries und installieren es
make install kopiert dabei die erstellte libphpcpp.so datei in das notwendige verzeichnis des systems /usr/lib und alle include files nach /usr/include und /usr/include/phpcpp.
zum erstellen eines Modules brauchen wir mindestens 3 Dateien:
die inhalte der dateien sehen dabei folgender maßen aus:
my_extension.cpp:
my_extension.ini
Makefile
um dieses modul zu erstellen, wechselt man in das verzeichnis mit dem Source und gibt
ein. Die so erstellten Dateien müssen danach mit
an die notwendigen Plätze kopiert werden. Dabei werden my_extension.so nach /usr/lib/php/20151012 kopiert und my_extension.ini nach /etc/php/7.0/mods-available:
Nun müssen wir das verfügbar gemachte modul noch mit enmod aktivieren:
mit php -m
grep my_extension kann man die funktionalität überprüfen (die ausgabe sollte ungefähr wie folgt aussehen):
um nun noch unser Modul zu testen, schreiben wir uns eine kleine php datei mit folgendem inhalt:
und führen sie in der console aus:
nun sollte die ausgabe ungefähr wie folgt lauten:
damit haben wir unser erstes Modul für PHP erstellt.
Probleme:
- es kann die Ausgabe von PHP Fatal error: Uncaught Error: Call to undefined function myFunction() in .* kommen. das bedeutet, dass das modul nicht geladen ist.
- beim erstellen kam folgender fehler:
das lag daran, das ich ein veraltetes tutorial verwendete, wo man die funktion an PHP extension noch mit folgender syntax addete:
das ist deprecated und funktioniert so nicht mehr.
Zu erst installieren wir die php development files:
[code lang=bash]
sudo apt-get install php-dev
zusätzlich für php 5.x:
sudo apt-get install php5-dev
oder für php 7.x
sudo apt-get install php7.0-dev
[/code]
Danach laden wir uns PHPCpp herunter unter PHPCpp auf Github.
dann gehen wir in das verzeichnis, erstellen die binaries und installieren es
BASH code
cd PHP-CPP make sudo make install
make install kopiert dabei die erstellte libphpcpp.so datei in das notwendige verzeichnis des systems /usr/lib und alle include files nach /usr/include und /usr/include/phpcpp.
zum erstellen eines Modules brauchen wir mindestens 3 Dateien:
- [LP]my_extension.cpp
- [LP]my_extension.ini
- [LP] natürlich eine Makefile
die inhalte der dateien sehen dabei folgender maßen aus:
my_extension.cpp:
CPP code
#include "phpcpp.h" #include "stdlib.h" Php::Value myFunction() { if (0 == rand() % 2) { return "string"; } return 123; } extern "C" { PHPCPP_EXPORT void *get_module() { static Php::Extension extension("my_extension", "1.0"); extension.add<myFunction>("myFunction"); return extension; } }
my_extension.ini
BASH code
extension=my_extension.so
Makefile
BASH code
NAME = my_extension UBUNTU_MAJOR := $(shell /usr/bin/lsb_release -r -s
cut -f1 -d.) OVER_SIXTEEN := $(shell echo "${UBUNTU_MAJOR} >= 16"
bc) OVER_FOURTEEN := $(shell echo "${UBUNTU_MAJOR} >= 14"
bc) ifeq (${OVER_SIXTEEN}, 1) INI_DIR = /etc/php/7.0/mods-available/ else ifeq (${OVER_FOURTEEN}, 1) INI_DIR = /etc/php5/mods-available/ else INI_DIR = /etc/php5/conf.d/ endif # # The extension dirs # # This is normally a directory like /usr/lib/php5/20121221 (based on the # PHP version that you use. We make use of the command line 'php-config' # instruction to find out what the extension directory is, you can override # this with a different fixed directory # EXTENSION_DIR = $(shell php-config --extension-dir) # # The name of the extension and the name of the .ini file # # These two variables are based on the name of the extension. We simply add # a certain extension to them (.so or .ini) # EXTENSION = ${NAME}.so INI = ${NAME}.ini # # Compiler # # By default, the GNU C++ compiler is used. If you want to use a different # compiler, you can change that here. You can change this for both the # compiler (the program that turns the c++ files into object files) and for # the linker (the program that links all object files into the single .so # library file. By default, g++ (the GNU C++ compiler) is used for both. # COMPILER = g++ LINKER = g++ # # Compiler and linker flags # # This variable holds the flags that are passed to the compiler. By default, # we include the -O2 flag. This flag tells the compiler to optimize the code, # but it makes debugging more difficult. So if you're debugging your application, # you probably want to remove this -O2 flag. At the same time, you can then # add the -g flag to instruct the compiler to include debug information in # the library (but this will make the final libphpcpp.so file much bigger, so # you want to leave that flag out on production servers). # # If your extension depends on other libraries (and it does at least depend on # one: the PHP-CPP library), you should update the LINKER_DEPENDENCIES variable # with a list of all flags that should be passed to the linker. # COMPILER_FLAGS = -Wall -c -O2 -std=c++11 -fpic -o LINKER_FLAGS = -shared LINKER_DEPENDENCIES = -lphpcpp # # Command to remove files, copy files and create directories. # # I've never encountered a *nix environment in which these commands do not work. # So you can probably leave this as it is # RM = rm -f CP = cp -f MKDIR = mkdir -p # # All source files are simply all *.cpp files found in the current directory # # A built-in Makefile macro is used to scan the current directory and find # all source files. The object files are all compiled versions of the source # file, with the .cpp extension being replaced by .o. # SOURCES = $(wildcard *.cpp) OBJECTS = $(SOURCES:%.cpp=%.o) # # From here the build instructions start # all: ${OBJECTS} ${EXTENSION} ${EXTENSION}: ${OBJECTS} ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES} ${OBJECTS}: ${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp} install: ${CP} ${EXTENSION} ${EXTENSION_DIR} ${CP} ${INI} ${INI_DIR} clean: ${RM} ${EXTENSION} ${OBJECTS}
um dieses modul zu erstellen, wechselt man in das verzeichnis mit dem Source und gibt
BASH code
make
ein. Die so erstellten Dateien müssen danach mit
BASH code
sudo make install
an die notwendigen Plätze kopiert werden. Dabei werden my_extension.so nach /usr/lib/php/20151012 kopiert und my_extension.ini nach /etc/php/7.0/mods-available:
BASH code
(ausgabe von make install): cp -f my_extension.so /usr/lib/php/20151012 cp -f my_extension.ini /etc/php/7.0/mods-available/
Nun müssen wir das verfügbar gemachte modul noch mit enmod aktivieren:
BASH code
sudo phpenmod my_extension
mit php -m
grep my_extension kann man die funktionalität überprüfen (die ausgabe sollte ungefähr wie folgt aussehen):
BASH code
php -m
grep my_extension my_extension
um nun noch unser Modul zu testen, schreiben wir uns eine kleine php datei mit folgendem inhalt:
PHP code
<?php echo "Teste 1".PHP_EOL; for ($i = 0; $i < 10; ++$i) { echo (myFunction().PHP_EOL); }
und führen sie in der console aus:
BASH code
php my_extension.php
nun sollte die ausgabe ungefähr wie folgt lauten:
BASH code
Teste 1 123 string 123 123 123 123 string string 123 123
damit haben wir unser erstes Modul für PHP erstellt.
Probleme:
- es kann die Ausgabe von PHP Fatal error: Uncaught Error: Call to undefined function myFunction() in .* kommen. das bedeutet, dass das modul nicht geladen ist.
- beim erstellen kam folgender fehler:
BASH code
my_extension.cpp: In function ‘void* get_module()’: my_extension.cpp:14:32: error: statement cannot resolve address of overloaded function extension.add<"myFunction">; ^ Makefile:100: die Regel für Ziel „my_extension.o“ scheiterte make: *** [my_extension.o] Fehler 1
das lag daran, das ich ein veraltetes tutorial verwendete, wo man die funktion an PHP extension noch mit folgender syntax addete:
CPP code
extension.add("myFunction", myFunction);
das ist deprecated und funktioniert so nicht mehr.