├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Examples ├── CallPhpFunctions │ ├── 30-callphpfunction.ini │ ├── Makefile │ ├── callphpfunction.cpp │ └── callphpfunction.php ├── ConstStaticProp │ ├── cpp │ │ ├── Makefile │ │ ├── mytestext.cpp │ │ ├── mytestext.h │ │ └── mytestext.ini │ ├── readme │ └── test.php ├── CppClassesInPhp │ ├── Makefile │ ├── check_map.php │ ├── cppclassinphp.cpp │ ├── cppclassinphp.ini │ ├── cppclassinphp.php │ └── includeMyCustomClass.h ├── DlUnrestricted │ ├── Makefile │ ├── dlunrestricted.cpp │ ├── dlunrestricted.ini │ └── dlunrestricted.php ├── EmptyExtension │ ├── Makefile │ ├── main.cpp │ └── yourextension.ini ├── Exceptions │ ├── ExceptionCatch │ │ ├── 30-exceptionCatch.ini │ │ ├── Makefile │ │ ├── exception.php │ │ └── exceptionCatch.cpp │ └── ExceptionThrow │ │ ├── 30-exceptionThrow.ini │ │ ├── Makefile │ │ ├── exception.php │ │ └── exceptionThrow.cpp ├── Extension │ ├── 30-phpcpp.ini │ ├── Makefile │ ├── extension.cpp │ └── extension.php ├── FunctionNoParameters │ ├── 30-functionnoparameters.ini │ ├── Makefile │ ├── functionnoparameters.cpp │ └── functionnoparameters.php ├── FunctionReturnValue │ ├── 30-functionreturnvalue.ini │ ├── Makefile │ ├── functionreturnvalue.cpp │ └── functionreturnvalue.php ├── FunctionVoid │ ├── 30-functionvoid.ini │ ├── Makefile │ ├── functionvoid.cpp │ └── functionvoid.php ├── FunctionWithParameters │ ├── 30-functionwithparameters.ini │ ├── Makefile │ ├── functionwithparameters.cpp │ └── functionwithparameters.php ├── Globals │ ├── 30-globals.ini │ ├── Makefile │ ├── globals.cpp │ └── globals.php ├── IncludeOnce │ ├── 30-includeonce.ini │ ├── Makefile │ ├── class.php │ ├── includeonce.cpp │ └── includeonce.php ├── Makefile ├── README.md ├── ReturnObject │ ├── Makefile │ ├── child.h │ ├── main.cpp │ ├── master.h │ ├── returnobject.ini │ └── test.php └── simple │ ├── 30-phpcpp.ini │ ├── Makefile │ ├── simple.cpp │ └── simple.php ├── LICENSE ├── Makefile ├── README.md ├── common ├── extensionbase.h ├── includes.h ├── modifiers.cpp ├── streambuf.cpp └── streambuf.h ├── documentation ├── bubblesort.html ├── calling-functions-and-methods.html ├── classes-and-objects.html ├── constants.html ├── constructors-and-destructors.html ├── dynamic-loading.html ├── exceptions.html ├── extension-callbacks.html ├── functions.html ├── inheritance.html ├── ini.html ├── install.html ├── lambda-functions.html ├── loading-extensions.html ├── magic-interfaces.html ├── magic-methods.html ├── namespaces.html ├── output-and-errors.html ├── parameters.html ├── properties.html ├── special-features.html ├── ten-reasons-for-using-php-cpp.html ├── variables.html └── your-first-extension.html ├── include ├── argument.h ├── array.h ├── arrayaccess.h ├── base.h ├── byref.h ├── byval.h ├── call.h ├── class.h ├── classbase.h ├── classtype.h ├── constant.h ├── countable.h ├── deprecated.h ├── error.h ├── exception.h ├── extension.h ├── file.h ├── function.h ├── global.h ├── globals.h ├── hashmember.h ├── hashparent.h ├── ini.h ├── inivalue.h ├── interface.h ├── iterator.h ├── message.h ├── modifiers.h ├── namespace.h ├── noexcept.h ├── object.h ├── parameters.h ├── platform.h ├── script.h ├── serializable.h ├── stream.h ├── streams.h ├── super.h ├── thread_local.h ├── throwable.h ├── traversable.h ├── type.h ├── value.h ├── valueiterator.h ├── version.h ├── visibility.h ├── zendcallable.h └── zval.h ├── phpcpp.h └── zend ├── arithmetic.h ├── base.cpp ├── boolmember.h ├── callable.cpp ├── callable.h ├── classbase.cpp ├── classimpl.cpp ├── classimpl.h ├── classtype.h ├── compileroptions.h ├── constant.cpp ├── constantfuncs.cpp ├── constantimpl.h ├── delayedfree.h ├── error.cpp ├── eval.cpp ├── exception.cpp ├── exception_handler.cpp ├── execarguments.h ├── executestate.h ├── exists.cpp ├── extension.cpp ├── extensionimpl.cpp ├── extensionimpl.h ├── extensionpath.h ├── file.cpp ├── floatmember.h ├── function.cpp ├── functor.cpp ├── functor.h ├── global.cpp ├── globals.cpp ├── hashiterator.h ├── hashmember.cpp ├── includes.h ├── ini.cpp ├── init.h ├── inivalue.cpp ├── interface.cpp ├── invaliditerator.h ├── iteratorimpl.cpp ├── iteratorimpl.h ├── lowercase.h ├── macros.h ├── member.h ├── members.cpp ├── method.h ├── module.cpp ├── module.h ├── namespace.cpp ├── nativefunction.h ├── notimplemented.h ├── nullmember.h ├── numericmember.h ├── object.cpp ├── objectimpl.h ├── opcodes.h ├── parametersimpl.h ├── property.h ├── rethrowable.h ├── sapi.cpp ├── script.cpp ├── state.h ├── stream.cpp ├── streambuf.cpp ├── streams.cpp ├── string.h ├── stringmember.h ├── super.cpp ├── symbol.h ├── throwable.cpp ├── traverseiterator.h ├── value.cpp ├── valueiterator.cpp ├── valueiteratorimpl.h ├── zendcallable.cpp └── zval.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.o 3 | *.a 4 | *.so 5 | *.txt 6 | *.a.* 7 | *.so.* 8 | build/ 9 | .vscode/ 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Although this is a C++ project, we use different PHP versions 2 | language: php 3 | 4 | # we need bionic 5 | dist: trusty 6 | sudo: required 7 | group: edge 8 | 9 | php: 10 | - 7.0 11 | - 7.1 12 | - 7.2 13 | - 7.3 14 | - 7.4 15 | - 8.0 16 | - nightly 17 | 18 | 19 | # setting the env is the easiest, because it will mix with all the separate php versions (travis does this) 20 | env: 21 | - COMPILER_PKG=g++-4.8 COMPILER=g++-4.8 22 | - COMPILER_PKG=g++-4.9 COMPILER=g++-4.9 23 | - COMPILER_PKG=g++-5 COMPILER=g++-5 24 | - COMPILER_PKG=g++-6 COMPILER=g++-6 25 | - COMPILER_PKG=g++-7 COMPILER=g++-7 26 | - COMPILER_PKG=g++-8 COMPILER=g++-8 27 | - COMPILER_PKG=clang++-4 COMPILER=clang++-4.0 28 | - COMPILER_PKG=clang++-5 COMPILER=clang++-5.0 29 | - COMPILER_PKG=clang++-6 COMPILER=clang++-6.0 30 | 31 | matrix: 32 | allow_failures: 33 | - php: nightly 34 | 35 | before_install: 36 | # install access to all gcc compilers 37 | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 38 | 39 | # and all relevant clang compilers 40 | - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-4.0 main" 41 | - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main" 42 | - sudo apt-add-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main" 43 | 44 | # update package index and install correct compiler 45 | - sudo apt-get -y update 46 | - sudo apt-get -y --allow-unauthenticated --no-install-recommends install ${COMPILER_PKG} 47 | 48 | script: 49 | # simply make the project with the set compiler 50 | - make -j4 COMPILER=$COMPILER && sudo make install 51 | -------------------------------------------------------------------------------- /Examples/CallPhpFunctions/30-callphpfunction.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=callphpfunction.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/CallPhpFunctions/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | PHP_CONFIG = $(shell which php-config) 5 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 6 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 7 | 8 | LD = g++ 9 | LD_FLAGS = -Wall -shared -O2 10 | RESULT = callphpfunction.so 11 | 12 | PHPINIFILE = 30-callphpfunction.ini 13 | 14 | SOURCES = $(wildcard *.cpp) 15 | OBJECTS = $(SOURCES:%.cpp=%.o) 16 | 17 | all: ${OBJECTS} ${RESULT} 18 | 19 | ${RESULT}: ${OBJECTS} 20 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 21 | 22 | clean: 23 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 24 | 25 | ${OBJECTS}: 26 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 27 | 28 | install: 29 | cp -f ${RESULT} ${LIBRARY_DIR}/ 30 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 31 | 32 | uninstall: 33 | rm ${LIBRARY_DIR}/${RESULT} 34 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 35 | -------------------------------------------------------------------------------- /Examples/CallPhpFunctions/callphpfunction.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * callphpfunction.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a php function call in C++. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | #include 13 | 14 | /** 15 | * Namespace to use 16 | */ 17 | using namespace std; 18 | 19 | /** 20 | * call_php_function() 21 | * Calls a function in PHP space. 22 | * @param ¶ms 23 | * @return Php::Value 24 | */ 25 | Php::Value call_php_function(Php::Parameters ¶ms) 26 | { 27 | // check whether the parameter is callable 28 | if (!params[0].isCallable()) throw Php::Exception("Not a callable type."); 29 | 30 | // perform the callback 31 | return params[0](1,2,3); 32 | } 33 | 34 | 35 | // Symbols are exported according to the "C" language 36 | extern "C" 37 | { 38 | // export the "get_module" function that will be called by the Zend engine 39 | PHPCPP_EXPORT void *get_module() 40 | { 41 | // create extension 42 | static Php::Extension extension("call_php_function","1.0"); 43 | 44 | // add function to extension 45 | extension.add("call_php_function", { 46 | Php::ByVal("addFunc", Php::Type::Callable), 47 | Php::ByVal("x", Php::Type::Numeric) 48 | }); 49 | 50 | // return the extension module 51 | return extension.module(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Examples/CallPhpFunctions/callphpfunction.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a php function call in C++. 7 | */ 8 | 9 | class MyClass 10 | { 11 | function method($a,$b,$c) 12 | { 13 | return $a+$b+$c; 14 | } 15 | } 16 | 17 | function myFunction($a,$b,$c) 18 | { 19 | return $a+$b+$c; 20 | } 21 | 22 | /** 23 | * Call a C++ function with a callable PHP function as its parameter. 24 | * The PHP function is then executed from the C++ code. 25 | * The PHP function is this case, adds three numbers. 26 | */ 27 | echo(call_php_function(function($a, $b, $c){ 28 | return $a + $b + $c; 29 | })."\n"); 30 | 31 | echo(call_php_function("myFunction")."\n"); 32 | 33 | echo(call_php_function(array(new MyClass(), 'method'))."\n"); 34 | -------------------------------------------------------------------------------- /Examples/ConstStaticProp/cpp/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = mytestext.so 12 | 13 | PHPINIFILE = mytestext.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} -------------------------------------------------------------------------------- /Examples/ConstStaticProp/cpp/mytestext.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * cppclassinphp.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of using a C++ class in PHP. 6 | */ 7 | 8 | #include "mytestext.h" 9 | /** 10 | * Namespace to use 11 | */ 12 | using namespace std; 13 | 14 | class MyTestExt : public Php::Base 15 | { 16 | 17 | public: 18 | MyTestExt() {} 19 | 20 | virtual ~MyTestExt() {} 21 | 22 | virtual void __construct() {} 23 | 24 | }; 25 | 26 | 27 | 28 | // Symbols are exported according to the "C" language 29 | extern "C" 30 | { 31 | // export the "get_module" function that will be called by the Zend engine 32 | PHPCPP_EXPORT void *get_module() 33 | { 34 | // create extension 35 | static Php::Extension extension("my_test_ext","0.1a"); 36 | 37 | // add the custom class ot the extension 38 | extension.add( 39 | "MyTestClass", 40 | Php::Class({ 41 | 42 | // Private PHP constructor! You can't instance object of MyTestClass 43 | Php::Private("__construct", Php::Method(&MyTestExt::__construct)), 44 | 45 | Php::Const("version", "v0.01-alpha"), 46 | Php::Const("PI", 3.14159265), 47 | Php::Const("IMISNULL"), 48 | }) 49 | ); 50 | 51 | // return the extension module 52 | return extension.module(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Examples/ConstStaticProp/cpp/mytestext.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The includes.h 3 | */ 4 | 5 | /** 6 | * Default Cpp libraries 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /** 13 | * Our own library. 14 | */ 15 | #include 16 | 17 | /** 18 | * Namespace to use 19 | */ 20 | using namespace std; 21 | 22 | /** 23 | * The test class. 24 | */ 25 | //#include "mycustomclass.h" 26 | -------------------------------------------------------------------------------- /Examples/ConstStaticProp/cpp/mytestext.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=mytestext.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/ConstStaticProp/readme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CopernicaMarketingSoftware/PHP-CPP/ad90b5a16e108f16a51afac3a4d92f6d72173db8/Examples/ConstStaticProp/readme -------------------------------------------------------------------------------- /Examples/ConstStaticProp/test.php: -------------------------------------------------------------------------------- 1 | $offset = $value; 41 | } 42 | } 43 | public function offsetExists($offset) { 44 | return isset($this->$offset); 45 | } 46 | public function offsetUnset($offset) { 47 | unset($this->$offset); 48 | } 49 | public function offsetGet($offset) { 50 | return isset($this->$offset) ? $this->$offset : null; 51 | } 52 | 53 | } 54 | 55 | class emptyClass {} 56 | 57 | $arr = array( 58 | 'qwe' => 'qweqweqweqw', 59 | 'asd' => 'Привет!', // check UTF-8 chars 60 | 'zxccvx' => 'sdfsecvyh6bug6yfty', 61 | 1=>2, 62 | '2'=>2, 63 | 44, 64 | new cl1(), 65 | '%'=>'%$%$%', 66 | ); 67 | 68 | $arr = new cl1(); 69 | 70 | $arr[5] = 55; 71 | $arr['strstr'] = 'strstrstrstrstrstr'; 72 | 73 | //$arr = new emptyClass(); 74 | //$arr = array(); 75 | 76 | 77 | $q = new MyClass(); 78 | 79 | var_export($arr); 80 | 81 | //$q->loopArray($arr); 82 | 83 | // Works for objects and arrays 84 | $q->loopObject($arr); 85 | //$q->loopObject($arr); 86 | 87 | -------------------------------------------------------------------------------- /Examples/CppClassesInPhp/cppclassinphp.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=cppclassinphp.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/CppClassesInPhp/cppclassinphp.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of using a C++ class in PHP. 7 | */ 8 | 9 | class TestClass 10 | { 11 | public $x = 1223; 12 | 13 | public function __construct() 14 | { 15 | echo("TestClass::__construct\n"); 16 | } 17 | 18 | } 19 | 20 | //create a MyCustomClass object, which is an object of a C++ class 21 | $object1 = new MyClass(); 22 | 23 | 24 | $object2 = $object1->myMethod(1); 25 | $object2->myMethod(1); 26 | 27 | echo("unset\n"); 28 | 29 | unset($object1); 30 | 31 | echo("got here\n"); 32 | 33 | return; 34 | 35 | //echo("prop x: ".$object1->x."\n"); 36 | 37 | $object1->x = 10; 38 | $object1->y = 20; 39 | 40 | echo("prop x: ".$object1->x."\n"); 41 | echo("prop y: ".$object1->y."\n"); 42 | 43 | $object2 = clone $object1; 44 | 45 | echo("prop x: ".$object2->x."\n"); 46 | echo("prop y: ".$object2->y."\n"); 47 | 48 | 49 | return; 50 | 51 | // run a function of the class 52 | $obj = $object->myMethod("MyClass"); 53 | 54 | echo(get_class($obj)."\n"); 55 | //echo($obj->format("Y-m-d")."\n"); 56 | 57 | //echo($obj->x."\n"); 58 | 59 | return; 60 | 61 | //$object->myMethod(2); 62 | 63 | echo($object->property1."\n"); 64 | echo($object->property2."\n"); 65 | -------------------------------------------------------------------------------- /Examples/CppClassesInPhp/includeMyCustomClass.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The includes.h 3 | */ 4 | 5 | /** 6 | * Default Cpp libraries 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /** 13 | * Our own library. 14 | */ 15 | #include 16 | 17 | /** 18 | * Namespace to use 19 | */ 20 | using namespace std; 21 | 22 | /** 23 | * The test class. 24 | */ 25 | //#include "mycustomclass.h" 26 | -------------------------------------------------------------------------------- /Examples/DlUnrestricted/dlunrestricted.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * functionvoid.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a void function call. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | 13 | /** 14 | * Function to load every possible extension by pathname 15 | * 16 | * It takes one argument: the filename of the PHP extension, and returns a 17 | * boolean to indicate whether the extension was correctly loaded. 18 | * 19 | * This function goes further than the original PHP dl() fuction, because 20 | * it does not check whether the passed in extension object is stored in the 21 | * right directory. Literally every possible extension, also local ones 22 | * created by end users, can be loaded. 23 | * 24 | * @param params Vector of parameters 25 | * @return boolean 26 | */ 27 | Php::Value dl_unrestricted(Php::Parameters ¶ms) 28 | { 29 | // get extension name 30 | std::string pathname = params[0]; 31 | 32 | // should it be opened persistently? 33 | bool persistent = params.size() > 1 ? params[1].boolValue() : false; 34 | 35 | // load the extension 36 | return Php::dl(pathname, persistent); 37 | } 38 | 39 | /** 40 | * Switch to C context to ensure that the get_module() function 41 | * is callable by C programs (which the Zend engine is) 42 | */ 43 | extern "C" { 44 | /** 45 | * Startup function that is called by the Zend engine 46 | * to retrieve all information about the extension 47 | * @return void* 48 | */ 49 | PHPCPP_EXPORT void *get_module() { 50 | // create static instance of the extension object 51 | static Php::Extension myExtension("dl_unrestricted", "1.0"); 52 | 53 | // the extension has one method 54 | myExtension.add("dl_unrestricted", { 55 | Php::ByVal("pathname", Php::Type::String) 56 | }); 57 | 58 | // return the extension 59 | return myExtension; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Examples/DlUnrestricted/dlunrestricted.ini: -------------------------------------------------------------------------------- 1 | ; configuration for dlunrestriced module 2 | extension=dlunrestricted.so 3 | 4 | -------------------------------------------------------------------------------- /Examples/DlUnrestricted/dlunrestricted.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a void function call. 7 | */ 8 | 9 | /* 10 | * Run the function with the given name. As you can see, the given name 11 | * can be different from the actual function name. 12 | */ 13 | my_void_function(); 14 | -------------------------------------------------------------------------------- /Examples/EmptyExtension/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * tell the compiler that the get_module is a pure C function 5 | */ 6 | extern "C" { 7 | 8 | /** 9 | * Function that is called by PHP right after the PHP process 10 | * has started, and that returns an address of an internal PHP 11 | * strucure with all the details and features of your extension 12 | * 13 | * @return void* a pointer to an address that is understood by PHP 14 | */ 15 | PHPCPP_EXPORT void *get_module() 16 | { 17 | // static(!) Php::Extension object that should stay in memory 18 | // for the entire duration of the process (that's why it's static) 19 | static Php::Extension extension("yourextension", "1.0"); 20 | 21 | // @todo add your own functions, classes, namespaces to the extension 22 | 23 | // return the extension 24 | return extension; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Examples/EmptyExtension/yourextension.ini: -------------------------------------------------------------------------------- 1 | extension=yourextension.so 2 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionCatch/30-exceptionCatch.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=exceptionCatch.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionCatch/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = exceptionCatch.so 12 | 13 | PHPINIFILE = 30-exceptionCatch.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionCatch/exception.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This example shows the working of a C++ function that throws an 8 | * exception, and that exception is then caught by PHP code. 9 | * 10 | */ 11 | 12 | // call the second C++ function that accepts a callback 13 | my_catch_exception_function(function($a, $b, $c) { 14 | 15 | // throw an exception from PHP - the C++ code will catch this exception 16 | throw new Exception("Example exception"); 17 | }); 18 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * exception.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a C++ function that 6 | * takes a callback function as parameter, and handles the 7 | * exception thrown by the callback function. 8 | */ 9 | 10 | /** 11 | * Libraries used. 12 | */ 13 | #include 14 | #include 15 | 16 | /** 17 | * Namespace to use 18 | */ 19 | using namespace std; 20 | 21 | /** 22 | * my_catch_exception_function() 23 | * Catches the exception thrown by the PHP callback function. 24 | * @param Php::Parameters 25 | */ 26 | void my_catch_exception_function(Php::Parameters ¶ms) 27 | { 28 | // the first parameter should be a callback 29 | Php::Value callback = params[0]; 30 | 31 | // this must be a callable type 32 | if (!callback.isCallable()) throw Php::Exception("Parameter 0 is not a function"); 33 | 34 | // we're going to call a function that could throw an exception, start a 35 | // try-catch block to deal with that 36 | try 37 | { 38 | // call the function 39 | callback("some","example","parameters"); 40 | } 41 | catch (Php::Exception &exception) 42 | { 43 | // handle the exception that was thrown from PHP space 44 | std::cout << "exception caught in CPP code" << std::endl; 45 | } 46 | } 47 | 48 | 49 | // Symbols are exported according to the "C" language 50 | extern "C" 51 | { 52 | // export the "get_module" function that will be called by the Zend engine 53 | PHPCPP_EXPORT void *get_module() 54 | { 55 | // create extension 56 | static Php::Extension extension("my_exception_catch","1.0"); 57 | 58 | // add function to extension 59 | extension.add("my_catch_exception_function"); 60 | 61 | // return the extension module 62 | return extension.module(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionThrow/30-exceptionThrow.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=exceptionThrow.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionThrow/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = exceptionThrow.so 12 | 13 | PHPINIFILE = 30-exceptionThrow.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionThrow/exception.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * This example shows the working of a C++ function that throws an 8 | * exception, and that exception is then caught by PHP code. 9 | * 10 | */ 11 | 12 | // try-catch block to be able to handle the exception 13 | try 14 | { 15 | // the my_throw_exception function is implemented in C++. and 16 | // it is going to throw an exception 17 | my_throw_exception_function(); 18 | } 19 | catch (Exception $exception) 20 | { 21 | // the exception object is thrown by C++ code, and caught by PHP 22 | // code 23 | echo $exception->getMessage(). "\n"; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Exceptions/ExceptionThrow/exceptionThrow.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * exception.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a C++ function that 6 | * throws an exception, which can be caught by PHP. 7 | * 8 | */ 9 | 10 | /** 11 | * Libraries used. 12 | */ 13 | #include 14 | 15 | /** 16 | * Namespace to use 17 | */ 18 | using namespace std; 19 | 20 | /** 21 | * my_throw_exception_function() 22 | * Throws an exception which should be caught by PHP. 23 | */ 24 | void my_throw_exception_function() 25 | { 26 | throw Php::Exception("I threw an exception in my_throw_exception_function()"); 27 | } 28 | 29 | 30 | // Symbols are exported according to the "C" language 31 | extern "C" 32 | { 33 | // export the "get_module" function that will be called by the Zend engine 34 | PHPCPP_EXPORT void *get_module() 35 | { 36 | // create extension 37 | static Php::Extension extension("my_exception_throw","1.0"); 38 | 39 | // add function to extension 40 | extension.add("my_throw_exception_function"); 41 | 42 | // return the extension module 43 | return extension.module(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Examples/Extension/30-phpcpp.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=extension.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/Extension/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = extension.so 12 | 13 | PHPINIFILE = 30-phpcpp.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/Extension/extension.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * extension.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of an extension. 6 | */ 7 | // library include 8 | #include 9 | 10 | /** 11 | * Namespace to use 12 | */ 13 | using namespace std; 14 | 15 | // Symbols are exported according to the "C" language 16 | extern "C" 17 | { 18 | // export the "get_module" function that will be called by the Zend engine 19 | PHPCPP_EXPORT void *get_module() 20 | { 21 | // create extension 22 | static Php::Extension extension("my_simple_extension","1.0"); 23 | 24 | // return the extension module 25 | return extension.module(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Examples/Extension/extension.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of an extension. 7 | */ 8 | 9 | // print all the extensions currently loaded. 10 | print_r(get_loaded_extensions()); 11 | -------------------------------------------------------------------------------- /Examples/FunctionNoParameters/30-functionnoparameters.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=functionnoparameters.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/FunctionNoParameters/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = functionnoparameters.so 12 | 13 | PHPINIFILE = 30-functionnoparameters.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} -------------------------------------------------------------------------------- /Examples/FunctionNoParameters/functionnoparameters.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * functionnoparameters.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a function call without parameters. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | 13 | /** 14 | * Namespace to use 15 | */ 16 | using namespace std; 17 | 18 | /** 19 | * my_no_parameters_function() 20 | * @return Php::Value 21 | */ 22 | Php::Value my_no_parameters_function() 23 | { 24 | return "42"; 25 | } 26 | 27 | 28 | // Symbols are exported according to the "C" language 29 | extern "C" 30 | { 31 | // export the "get_module" function that will be called by the Zend engine 32 | PHPCPP_EXPORT void *get_module() 33 | { 34 | // create extension 35 | static Php::Extension extension("my_function_no_parameters","1.0"); 36 | 37 | // add function to extension 38 | extension.add("my_no_parameters_function"); 39 | 40 | // return the extension module 41 | return extension.module(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Examples/FunctionNoParameters/functionnoparameters.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a function call without parameters. 7 | */ 8 | 9 | 10 | //Run a function without parameters. 11 | echo my_no_parameters_function() . "\n"; 12 | -------------------------------------------------------------------------------- /Examples/FunctionReturnValue/30-functionreturnvalue.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=functionreturnvalue.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/FunctionReturnValue/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = functionreturnvalue.so 12 | 13 | PHPINIFILE = 30-functionreturnvalue.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/FunctionReturnValue/functionreturnvalue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * functionreturnvalue.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a function call with a return value. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | 13 | /** 14 | * Namespace to use 15 | */ 16 | using namespace std; 17 | 18 | /** 19 | * my_return_value_function() 20 | * @return Php::Value 21 | */ 22 | Php::Value my_return_value_function() 23 | { 24 | return "42"; 25 | } 26 | 27 | 28 | // Symbols are exported according to the "C" language 29 | extern "C" 30 | { 31 | // export the "get_module" function that will be called by the Zend engine 32 | PHPCPP_EXPORT void *get_module() 33 | { 34 | // create extension 35 | static Php::Extension extension("my_function_return_value","1.0"); 36 | 37 | // add function to extension 38 | extension.add("my_return_value_function"); 39 | 40 | // return the extension module 41 | return extension.module(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Examples/FunctionReturnValue/functionreturnvalue.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a function call with a return value. 7 | */ 8 | 9 | /** 10 | * Run a function which returns a value. 11 | */ 12 | echo my_return_value_function() . "\n"; 13 | -------------------------------------------------------------------------------- /Examples/FunctionVoid/30-functionvoid.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=functionvoid.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/FunctionVoid/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = functionvoid.so 12 | 13 | PHPINIFILE = 30-functionvoid.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/FunctionVoid/functionvoid.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * functionvoid.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a void function call. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | #include 13 | 14 | /** 15 | * Namespace to use 16 | */ 17 | using namespace std; 18 | 19 | /** 20 | * my_function_void() 21 | */ 22 | void my_function_void() 23 | { 24 | cout << "In my_function_void()" << endl; 25 | } 26 | 27 | 28 | // Symbols are exported according to the "C" language 29 | extern "C" 30 | { 31 | // export the "get_module" function that will be called by the Zend engine 32 | PHPCPP_EXPORT void *get_module() 33 | { 34 | // create extension 35 | static Php::Extension extension("my_function_void","1.0"); 36 | 37 | // add function to extension 38 | extension.add("my_void_function"); 39 | 40 | // return the extension module 41 | return extension.module(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Examples/FunctionVoid/functionvoid.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a void function call. 7 | */ 8 | 9 | /* 10 | * Run the function with the given name. As you can see, the given name 11 | * can be different from the actual function name. 12 | */ 13 | my_void_function(); 14 | -------------------------------------------------------------------------------- /Examples/FunctionWithParameters/30-functionwithparameters.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=functionwithparameters.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/FunctionWithParameters/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = functionwithparameters.so 12 | 13 | PHPINIFILE = 30-functionwithparameters.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/FunctionWithParameters/functionwithparameters.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a function call with parameters, defined and undefined. 7 | */ 8 | 9 | /* 10 | * Test class. 11 | */ 12 | class MyPhpClass { 13 | 14 | public $aMemberVar = "aMemberVar"; 15 | 16 | public function __toString() 17 | { 18 | return "myPhpClass.__toString()"; 19 | } 20 | 21 | public function getMemberVar() 22 | { 23 | return $aMemberVar; 24 | } 25 | } 26 | 27 | /* 28 | * Run a function with parameters. 29 | */ 30 | 31 | 32 | /* 33 | * A function which takes parameters, which are all undefined; 34 | * my_with_undefined_parameters_function('1st','2nd','3rd','4th') 35 | */ 36 | echo my_with_undefined_parameters_function('1st','2nd','3rd','4th') . "\n\n\n"; 37 | 38 | /* 39 | * A function which takes parameters, which are all defined; 40 | * my_with_defined_parameters_function(21,42) 41 | */ 42 | 43 | echo my_with_defined_parameters_function(21,42) . "\n\n\n"; 44 | 45 | /* 46 | * A function which takes a reference of a parameter 47 | * my_with_defined_parameters_reference_function(referenceVar) 48 | */ 49 | 50 | $referenceVar = "I am unchanged."; 51 | echo "The value of referenceVar: " . $referenceVar. "\n"; 52 | 53 | echo my_with_defined_parameters_reference_function($referenceVar) . "\n"; 54 | 55 | echo "New value of referenceVar: " . $referenceVar ."\n\n\n"; 56 | 57 | /* 58 | * A function which takes an array as a parameter 59 | * my_with_defined_array_parameters_function($myArray) 60 | */ 61 | $myArray = array("a", "b", "c", "d"); 62 | echo my_with_defined_array_parameters_function($myArray) . "\n\n\n"; 63 | 64 | /* 65 | * A function which takes an object as a parameter 66 | * my_with_defined_object_parameter_function(myPhpClass) 67 | */ 68 | 69 | $myPhpClass = new MyPhpClass; 70 | echo my_with_defined_object_parameters_function($myPhpClass); 71 | 72 | /* 73 | * Accessing a non-existant parameters index will result in a segmentation fault. 74 | * The segmentation fault will also occur when passing the wrong type of parameter. 75 | */ 76 | -------------------------------------------------------------------------------- /Examples/Globals/30-globals.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=globals.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/Globals/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -shared -O2 11 | RESULT = globals.so 12 | 13 | PHPINIFILE = 30-globals.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/Globals/globals.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * functionvoid.cpp 3 | * @author Emiel Bruijntjes 4 | * 5 | * An example file to show how global variables can be accessed 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | #include 13 | 14 | /** 15 | * Namespace to use 16 | */ 17 | using namespace std; 18 | 19 | /** 20 | * process_globals() 21 | * 22 | * This function reads and modifies global variables 23 | */ 24 | Php::Value process_globals() 25 | { 26 | // all global variables can be accessed via the Php::GLOBALS variable, 27 | // which is more or less the same as the PHP $_GLOBALS variable 28 | 29 | // set a global variable 30 | Php::GLOBALS["a"] = 1; 31 | 32 | // increment a global variable 33 | Php::GLOBALS["b"] += 1; 34 | 35 | // set a global variable to be an array 36 | Php::GLOBALS["c"] = Php::Array(); 37 | 38 | // add a member to an array 39 | Php::GLOBALS["c"]["member"] = 123; 40 | 41 | // and increment it 42 | Php::GLOBALS["c"]["member"] += 77; 43 | 44 | // change value e 45 | Php::GLOBALS["e"] = Php::GLOBALS["e"][0]("hello"); 46 | 47 | // if a global variable holds a function, we can call it 48 | return Php::GLOBALS["d"](1,2,3); 49 | } 50 | 51 | // Symbols are exported according to the "C" language 52 | extern "C" 53 | { 54 | // export the "get_module" function that will be called by the Zend engine 55 | PHPCPP_EXPORT void *get_module() 56 | { 57 | // create extension 58 | static Php::Extension extension("globals","1.0"); 59 | 60 | // add function to extension 61 | extension.add("process_globals"); 62 | 63 | // return the extension module 64 | return extension.module(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Examples/Globals/globals.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * An example file to show the working of a void function call. 7 | */ 8 | 9 | // we first need to set a number of globals 10 | $b = 10; 11 | $d = function($a,$b,$c) { 12 | return $a+$b+$c; 13 | }; 14 | 15 | // fun global var 16 | $e = array( 17 | function($a) { 18 | return $a; 19 | } 20 | ); 21 | 22 | 23 | // call the C++ function that will do something 24 | $d = process_globals(); 25 | 26 | // the global variable $a should not have the value 1 27 | echo("a = $a\n"); 28 | 29 | // the variable $b should not be 11 30 | echo("b = $b\n"); 31 | 32 | // $c should be an array with value 200 33 | echo("c['member'] = ".$c['member']."\n"); 34 | 35 | // $d is overwritten and now is 6 36 | echo("d = $d\n"); 37 | 38 | // e should be replaced by a string 39 | echo("e = $e\n"); -------------------------------------------------------------------------------- /Examples/IncludeOnce/30-includeonce.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=includeonce.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/IncludeOnce/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -O2 -std=c++11 4 | PHP_CONFIG = $(shell which php-config) 5 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 6 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 7 | 8 | LD = g++ 9 | LD_FLAGS = -Wall -shared -O2 10 | RESULT = includeonce.so 11 | 12 | PHPINIFILE = 30-includeonce.ini 13 | 14 | SOURCES = $(wildcard *.cpp) 15 | OBJECTS = $(SOURCES:%.cpp=%.o) 16 | 17 | all: ${OBJECTS} ${RESULT} 18 | 19 | ${RESULT}: ${OBJECTS} 20 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 21 | 22 | clean: 23 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 24 | 25 | ${OBJECTS}: 26 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 27 | 28 | install: 29 | cp -f ${RESULT} ${LIBRARY_DIR}/ 30 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 31 | 32 | uninstall: 33 | rm ${LIBRARY_DIR}/${RESULT} 34 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 35 | -------------------------------------------------------------------------------- /Examples/IncludeOnce/class.php: -------------------------------------------------------------------------------- 1 | 9 | * @copyright 2024 Copernica BV 10 | */ 11 | 12 | /** 13 | * Include ourselves (should do nothing) 14 | */ 15 | include_once(__FILE__); 16 | my_include_once(__FILE__); 17 | 18 | /** 19 | * Class definition 20 | */ 21 | class SillyClass {} 22 | -------------------------------------------------------------------------------- /Examples/IncludeOnce/includeonce.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * callphpfunction.cpp 3 | * @author Jasper van Eck 4 | * 5 | * An example file to show the working of a php function call in C++. 6 | */ 7 | 8 | /** 9 | * Libraries used. 10 | */ 11 | #include 12 | #include 13 | 14 | /** 15 | * Namespace to use 16 | */ 17 | using namespace std; 18 | 19 | /** 20 | * Function to test the Php::include_once() call 21 | * @param ¶ms 22 | */ 23 | void my_include_once(Php::Parameters ¶ms) 24 | { 25 | // the string 26 | Php::Value path = params[0]; 27 | 28 | // do the call 29 | Php::include_once(path.stringValue()); 30 | } 31 | 32 | 33 | // Symbols are exported according to the "C" language 34 | extern "C" 35 | { 36 | // export the "get_module" function that will be called by the Zend engine 37 | PHPCPP_EXPORT void *get_module() 38 | { 39 | // create extension 40 | static Php::Extension extension("include_once","1.0"); 41 | 42 | // add function to extension 43 | extension.add("my_include_once", { 44 | Php::ByVal("path", Php::Type::String), 45 | }); 46 | 47 | // return the extension module 48 | return extension.module(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Examples/IncludeOnce/includeonce.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2015 Copernica BV 8 | */ 9 | 10 | /** 11 | * Include guard 12 | */ 13 | #pragma once 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class Child : public Php::Base 19 | { 20 | public: 21 | /** 22 | * Constructor and destructor 23 | */ 24 | Child() {} 25 | virtual ~Child() {} 26 | 27 | /** 28 | * Cast to a string 29 | * @return const char * 30 | */ 31 | const char *__toString() const 32 | { 33 | return "this is the child"; 34 | } 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /Examples/ReturnObject/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "master.h" 3 | #include "child.h" 4 | 5 | /** 6 | * tell the compiler that the get_module is a pure C function 7 | */ 8 | extern "C" { 9 | 10 | /** 11 | * Function that is called by PHP right after the PHP process 12 | * has started, and that returns an address of an internal PHP 13 | * strucure with all the details and features of your extension 14 | * 15 | * @return void* a pointer to an address that is understood by PHP 16 | */ 17 | PHPCPP_EXPORT void *get_module() 18 | { 19 | // static(!) Php::Extension object that should stay in memory 20 | // for the entire duration of the process (that's why it's static) 21 | static Php::Extension extension("returnobjecy", "1.0"); 22 | 23 | // we have to class - master and child 24 | Php::Class master("master"); 25 | Php::Class child("child"); 26 | 27 | // the master class has one method - to return a child 28 | master.method<&Master::child>("child"); 29 | 30 | // add all classes to the extension 31 | extension.add(master); 32 | extension.add(child); 33 | 34 | // return the extension 35 | return extension; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Examples/ReturnObject/master.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Master.h 3 | * 4 | * Class that is exported to PHP space 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2015 Copernica BV 8 | */ 9 | 10 | /** 11 | * Include guard 12 | */ 13 | #pragma once 14 | 15 | /** 16 | * Dependencies 17 | */ 18 | #include "child.h" 19 | 20 | /** 21 | * Class definition 22 | */ 23 | class Master : public Php::Base 24 | { 25 | private: 26 | /** 27 | * One child 28 | * @var Php::Value 29 | */ 30 | Php::Value _value; 31 | 32 | public: 33 | /** 34 | * Constructor 35 | */ 36 | Master() 37 | { 38 | // create a child instance 39 | _value = Php::Object("Child", new Child()); 40 | } 41 | 42 | /** 43 | * Destructor 44 | */ 45 | virtual ~Master() {} 46 | 47 | /** 48 | * Retrieve the child 49 | * @return Php::Value 50 | */ 51 | Php::Value child() const 52 | { 53 | return _value; 54 | } 55 | 56 | /** 57 | * Cast to a string 58 | * @return const char * 59 | */ 60 | const char *__toString() const 61 | { 62 | return "this is the master"; 63 | } 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /Examples/ReturnObject/returnobject.ini: -------------------------------------------------------------------------------- 1 | extension=returnobject.so 2 | -------------------------------------------------------------------------------- /Examples/ReturnObject/test.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2015 Copernica BV 7 | */ 8 | 9 | /** 10 | * Construct master object 11 | * @var Master 12 | */ 13 | $master = new Master(); 14 | 15 | /** 16 | * Construct derived child object 17 | * @var Child 18 | */ 19 | $child1 = new Child(); 20 | 21 | /** 22 | * Fetch the child object that is stored as member var in the master 23 | * @var Child 24 | */ 25 | $child2 = $master->child(); 26 | 27 | /** 28 | * Show output, expected is: 29 | * this is the master 30 | * this is the child 31 | * this is the child 32 | */ 33 | echo(strval($master)."\n"); 34 | echo(strval($child1)."\n"); 35 | echo(strval($child2)."\n"); 36 | 37 | -------------------------------------------------------------------------------- /Examples/simple/30-phpcpp.ini: -------------------------------------------------------------------------------- 1 | ; configuration for phpcpp module 2 | ; priority=30 3 | extension=simple.so 4 | 5 | -------------------------------------------------------------------------------- /Examples/simple/Makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ 2 | RM = rm -f 3 | CPP_FLAGS = -Wall -c -I. -I/home/work/include/ -O2 -std=c++11 4 | 5 | PHP_CONFIG = $(shell which php-config) 6 | LIBRARY_DIR = $(shell ${PHP_CONFIG} --extension-dir) 7 | PHP_CONFIG_DIR = $(shell ${PHP_CONFIG} --ini-dir) 8 | 9 | LD = g++ 10 | LD_FLAGS = -Wall -Wl,-rpath,/home/work/lib -shared -O2 -L/home/work/lib 11 | RESULT = simple.so 12 | 13 | PHPINIFILE = 30-phpcpp.ini 14 | 15 | SOURCES = $(wildcard *.cpp) 16 | OBJECTS = $(SOURCES:%.cpp=%.o) 17 | 18 | all: ${OBJECTS} ${RESULT} 19 | 20 | ${RESULT}: ${OBJECTS} 21 | ${LD} ${LD_FLAGS} -o $@ ${OBJECTS} -lphpcpp 22 | 23 | clean: 24 | ${RM} *.obj *~* ${OBJECTS} ${RESULT} 25 | 26 | ${OBJECTS}: 27 | ${CPP} ${CPP_FLAGS} -fpic -o $@ ${@:%.o=%.cpp} 28 | 29 | install: 30 | cp -f ${RESULT} ${LIBRARY_DIR}/ 31 | cp -f ${PHPINIFILE} ${PHP_CONFIG_DIR}/ 32 | 33 | uninstall: 34 | rm ${LIBRARY_DIR}/${RESULT} 35 | rm ${PHP_CONFIG_DIR}/${PHPINIFILE} 36 | -------------------------------------------------------------------------------- /Examples/simple/simple.php: -------------------------------------------------------------------------------- 1 | a."\n"); 62 | // echo($this->b."\n"); 63 | // echo("hoi\n"); 64 | // 65 | // parent::myMethod($val); 66 | // } 67 | // 68 | //} 69 | // 70 | //$x = new my_extended_class(); 71 | //$x->myMethod(123); 72 | 73 | $x = new my_class(); 74 | $x->myMethod(); 75 | 76 | 77 | //echo(my_plus(1,2,3,4)."\n"); 78 | 79 | $array = array(); 80 | for ($i=0; $i<10000; $i++) $array[] = rand(); 81 | 82 | //$array = array(1,2,3); 83 | 84 | //print_r($array); 85 | //bubblesort($array); 86 | 87 | //print_r($array); 88 | 89 | 90 | //echo("my_class::a = ".$x->a."\n"); 91 | //echo("my_class::b = ".$x->b."\n"); 92 | // 93 | //unset($x); 94 | // 95 | //echo("done\n"); 96 | 97 | //$x->my_method(); 98 | 99 | 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP-CPP 2 | ======= 3 | 4 | [![Build Status](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP.svg?branch=master)](https://travis-ci.org/CopernicaMarketingSoftware/PHP-CPP) 5 | 6 | The PHP-CPP library is a C++ library for developing PHP extensions. It offers a collection 7 | of well documented and easy-to-use classes that can be used and extended to build native 8 | extensions for PHP. The full documentation can be found on http://www.php-cpp.com. 9 | 10 | ABOUT 11 | ===== 12 | 13 | PHP-CPP is created and maintained by Copernica (www.copernica.com). We write 14 | our code mostly in PHP and C++ and needed an effective way 15 | to combine these two languages. That's where PHP-CPP comes in. 16 | Do you appreciate our work and are you looking for other high quality solutions? 17 | 18 | Then check out our other solutions: 19 | 20 | * PHP-JS (www.php-js.com) 21 | * Copernica Marketing Suite (www.copernica.com) 22 | * MailerQ MTA (www.mailerq.com) 23 | * Responsive Email web service (www.responsiveemail.com) 24 | 25 | The power of PHP-CPP 26 | ==================== 27 | 28 | Unlike regular PHP extensions - which are really hard to implement and require a deep 29 | knowledge of the Zend engine and pointer manipulation - extensions built with PHP-CPP 30 | are not difficult to develop at all. In fact, the only thing you need to do is write a function in 31 | C++, and the PHP-CPP library uses all the power offered by C++11 to convert the parameters and return 32 | values from your functions to/and from PHP: 33 | 34 | ```c 35 | Php::Value hello_world() 36 | { 37 | return "hello world!"; 38 | } 39 | ``` 40 | 41 | The function above is a native C++ function. With PHP-CPP you can export this function 42 | to PHP with only one single C++ method call: 43 | 44 | ```c 45 | extension.add("hello_world", hello_world); 46 | ``` 47 | 48 | Working with parameters and return values is just as easy: 49 | 50 | ```c 51 | Php::Value my_plus(Php::Parameters ¶ms) 52 | { 53 | return params[0] + params[1]; 54 | } 55 | ``` 56 | 57 | The method call to export the above C++ function: 58 | 59 | ```c 60 | extension.add("my_plus", { 61 | Php::ByVal("a", Php::numericType), 62 | Php::ByVal("b", Php::numericType) 63 | }); 64 | ``` 65 | 66 | The PHP-CPP library ensures that the variables 67 | from PHP (which internally are complicated C structures), are automatically converted into 68 | integers, passed to your function, and that the return value of your "my_plus" function is 69 | also converted back into a PHP variable. 70 | 71 | Type conversion between native C/C++ types and PHP variables is handled by PHP-CPP, using 72 | features from the C++11 language. It does not matter if your functions accept strings, 73 | integers, booleans or other native parameters: PHP-CPP takes care of the conversion. 74 | The return value of your function is also transformed by PHP-CPP into PHP. 75 | 76 | More complicated structures can be handled by PHP-CPP as well. If you would like to return 77 | a nested associative array from your function, you can do so too: 78 | 79 | ```c 80 | Php::Value get_complex_array() 81 | { 82 | Php::Value r; 83 | r["a"] = 123; 84 | r["b"] = 456; 85 | r["c"][0] = "nested value"; 86 | r["c"][1] = "example"; 87 | return r; 88 | } 89 | ``` 90 | 91 | The C++ function above is equivalent to the following function in PHP: 92 | 93 | ```php 94 | function get_complex_array() 95 | { 96 | return array( 97 | "a" => 123, 98 | "b" => 456, 99 | "c" => array("nested_value","example") 100 | ); 101 | } 102 | ``` 103 | 104 | More information and more examples are available on the official website: 105 | http://www.php-cpp.com. 106 | -------------------------------------------------------------------------------- /common/includes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Includes.h 3 | * 4 | * All includes for compiling the common module files of PHP-CPP library 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Standard C and C++ libraries 12 | */ 13 | #include 14 | 15 | /** 16 | * Public include files 17 | */ 18 | #include "../include/visibility.h" 19 | #include "../include/modifiers.h" 20 | 21 | /** 22 | * Generic implementation header files 23 | */ 24 | #include "streambuf.h" 25 | -------------------------------------------------------------------------------- /common/modifiers.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Modifiers.cpp 3 | * 4 | * In this file an enumeration type is with the possible 5 | * member modifiers 6 | * 7 | * @author Martijn Otto 8 | * @author Emiel Bruijntjes 9 | * 10 | * @copyright 2014 Copernica BV 11 | */ 12 | #include "includes.h" 13 | #include 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * The modifiers are constants 22 | */ 23 | #if PHP_VERSION_ID < 70400 24 | const int Static = 0x01; 25 | const int Abstract = 0x02; 26 | const int Final = 0x04; 27 | const int Public = 0x100; 28 | const int Protected = 0x200; 29 | const int Private = 0x400; 30 | const int Const = 0; 31 | #else 32 | const int Static = 0x10; 33 | const int Abstract = 0x40; 34 | const int Final = 0x20; 35 | const int Public = 0x01; 36 | const int Protected = 0x02; 37 | const int Private = 0x04; 38 | const int Const = 0; 39 | #endif 40 | 41 | /** 42 | * Modifiers that are supported for methods and properties 43 | */ 44 | const int MethodModifiers = Final | Public | Protected | Private | Static; 45 | const int PropertyModifiers = Final | Public | Protected | Private | Const | Static; 46 | 47 | /** 48 | * End namespace 49 | */ 50 | } 51 | -------------------------------------------------------------------------------- /common/streambuf.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * StreamBuf.cpp 3 | * 4 | * Implementation file for the StreamBuf class 5 | * 6 | * @see http://www.mr-edd.co.uk/blog/beginners_guide_streambuf 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | #include "includes.h" 12 | 13 | /** 14 | * Set up namespace 15 | */ 16 | namespace Php { 17 | 18 | /** 19 | * Constructor 20 | * @param error 21 | */ 22 | StreamBuf::StreamBuf(int error) : _error(error) 23 | { 24 | // we reserve one byte, so that when overflow is called, we still have one 25 | // byte extra in the buffer to put the overflowed byte int 26 | setp(_buffer, _buffer+1024-1); 27 | } 28 | 29 | 30 | /** 31 | * Method that is called when the internal buffer overflows 32 | * @param c 33 | * @return int 34 | */ 35 | int StreamBuf::overflow(int c) 36 | { 37 | // for error buffers, overflow is simply discarded 38 | if (_error) return c; 39 | 40 | // end-of-file has not output, we call EOF directly, and by using the 41 | // comma operator we ensure that EOF is returned 42 | if (c == EOF) return sync(), EOF; 43 | 44 | // because we lied the underlying buffer about the size of the buffer 45 | // by one byte, there is no real overflow, and we can still add the byte 46 | // to the end of the buffer 47 | *pptr() = c; 48 | 49 | // increment buffer size 50 | pbump(1); 51 | 52 | // and now we're going to syn the buffer 53 | return sync() == -1 ? EOF : c; 54 | } 55 | 56 | /** 57 | * End namespace 58 | */ 59 | } 60 | -------------------------------------------------------------------------------- /common/streambuf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * StreamBuf.h 3 | * 4 | * PHP output stream buffer which is used by the Php::out object to 5 | * have an output stream just like the regular std::ostream buffers, 6 | * but that sends all output to PHP output 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | 12 | /** 13 | * Set up namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Issue reported by user on a Windows / Mingw32 platform: EOF was 19 | * not defined. Let's defined it ourselves 20 | */ 21 | #ifndef EOF 22 | # define EOF (-1) 23 | #endif 24 | 25 | /** 26 | * Class definition 27 | */ 28 | class StreamBuf : public std::streambuf 29 | { 30 | public: 31 | /** 32 | * Constructor 33 | * @param error the error type, or 0 for regular output 34 | */ 35 | StreamBuf(int error); 36 | 37 | /** 38 | * No copying or moving 39 | * @param that 40 | */ 41 | StreamBuf(const StreamBuf &that) = delete; 42 | StreamBuf(StreamBuf &&that) = delete; 43 | 44 | /** 45 | * Destructor 46 | */ 47 | virtual ~StreamBuf() {} 48 | 49 | /** 50 | * No copying or moving 51 | * @param that 52 | */ 53 | StreamBuf &operator=(const StreamBuf &that) = delete; 54 | StreamBuf &operator=(StreamBuf &&that) = delete; 55 | 56 | protected: 57 | /** 58 | * Method that is called when the internal buffer overflows 59 | * @param c 60 | * @return int 61 | */ 62 | virtual int overflow(int c = EOF) override; 63 | 64 | /** 65 | * Called when the internal buffer should be synchronized 66 | * @return int 67 | */ 68 | virtual int sync() override; 69 | 70 | private: 71 | /** 72 | * The error type, or 0 for regular output 73 | * @var int 74 | */ 75 | int _error; 76 | 77 | /** 78 | * The internal buffer 79 | * @var char[] 80 | */ 81 | char _buffer[1024]; 82 | }; 83 | 84 | /** 85 | * End namespace 86 | */ 87 | } 88 | 89 | -------------------------------------------------------------------------------- /documentation/ini.html: -------------------------------------------------------------------------------- 1 |

Reading php.ini variables

2 |

3 | Reading settings from the php.ini file(s) is just as simple as it 4 | is to obtain these settings from a regular PHP script. Inside a PHP script 5 | you can use the built-in ini_get() function to read settings from the php.ini 6 | file, and in your C++ extension you use the Php::ini_get() function. 7 |

8 |

9 |

#include <phpcpp.h>
 10 | 
 11 | /**
 12 |  *  Simple function that is used to demonstrate how settings from the
 13 |  *  php.ini file can be read
 14 |  */
 15 | void myFunction()
 16 | {
 17 |     // read in the "output_buffering" variable from the php.ini file
 18 |     int output_buffering = Php::ini_get("output_buffering");
 19 |     
 20 |     // read in the "variables_order" variable
 21 |     std::string variables_order = Php::ini_get("variables_order");
 22 | }
 23 | 
 24 | /**
 25 |  *  Switch to C contect so that the get_module() function can be
 26 |  *  called by the Zend engine
 27 |  */
 28 | extern "C" {
 29 |     /**
 30 |      *  The get_module() startup function
 31 |      *  @return void*
 32 |      */
 33 |     PHPCPP_EXPORT void *get_module() {
 34 |         
 35 |         // create extension object
 36 |         static Php::Extension extension("my_extension", "1.0");
 37 |         
 38 |         // export one function
 39 |         extension.add("myFunction", myFunction);
 40 |         
 41 |         // return a pointer to the extension object
 42 |         return extension;
 43 |     }
 44 | }
45 |

46 |

47 | The Php::ini_get() function returns an object that can be assigned to 48 | strings, integers and floating point numbers. In the above example we have 49 | used this to assign the settings directly to an integer and a std::string. 50 |

51 |

52 | You can only retrieve predefined variables from the php.ini. It is thus not 53 | possible to call Php::ini_get() with random strings. If you want to use 54 | your own variables, you must first register them in the get_module() 55 | function before you can call Php::ini_get() to retrieve the current values. 56 |

57 |

58 |

#include <phpcpp.h>
 59 | 
 60 | /**
 61 |  *  Simple function that is used to demonstrate how settings from the
 62 |  *  php.ini file can be read
 63 |  */
 64 | void myFunction()
 65 | {
 66 |     // read in a variable defined for this extension
 67 |     int var1 = Php::ini_get("my_extension.var1");
 68 |     
 69 |     // read in a string variable
 70 |     std::string var2 = Php::ini_get("my_extension.var2");
 71 | }
 72 | 
 73 | /**
 74 |  *  Switch to C contect so that the get_module() function can be
 75 |  *  called by the Zend engine
 76 |  */
 77 | extern "C" {
 78 |     /**
 79 |      *  The get_module() startup function
 80 |      *  @return void*
 81 |      */
 82 |     PHPCPP_EXPORT void *get_module() {
 83 |         
 84 |         // create extension object
 85 |         static Php::Extension extension("my_extension", "1.0");
 86 |         
 87 |         // export one function
 88 |         extension.add("myFunction", myFunction);
 89 |         
 90 |         // tell the PHP engine that the php.ini variables my_extension.var1
 91 |         // and my_extension.var2 are usable
 92 |         extension.add(Php::Ini("my_extension.var1", "default-value"));
 93 |         extension.add(Php::Ini("my_extension.var2", 12345));
 94 |         
 95 |         // return a pointer to the extension object
 96 |         return extension;
 97 |     }
 98 | }
99 |

100 | -------------------------------------------------------------------------------- /documentation/namespaces.html: -------------------------------------------------------------------------------- 1 |

Namespaces

2 |

3 | Although namespaces have a very rich implementation in PHP scripts, 4 | with special keyswords like 'use' and 'namespace' and special constants 5 | like '__NAMESPACE__', they are internally very simple. 6 |

7 |

8 | A namespace is nothing else than a class or function prefix. If you want your classes 9 | or functions to appear in a specific namespace, you simply have to add 10 | a prefix to the class or function name. The following code creates a 11 | function "myFunction" in the "myNamespace" namespace. 12 |

13 |

14 |

#include <phpcpp.h>
15 | 
16 | // function that we're going to export
17 | void myFunction()
18 | {
19 | }
20 | 
21 | extern "C" {
22 |     PHPCPP_EXPORT void *get_module() {
23 |         
24 |         // create extension object
25 |         static Php::Extension extension("my_extension", "1.0");
26 |         
27 |         // add the myFunction function to the extension, 
28 |         // and put it in namespace "myNamespace"
29 |         extension.add("myNamespace\\myFunction", myFunction);
30 |         
31 |         // return the extension
32 |         return extension;
33 |     }
34 | }
35 |

36 |

37 | If you like, you can use the Php::Namespace utility class for this. This is a 38 | class with exactly the same signature as the Php::Extension class, and 39 | that you can use to register classes and functions too. 40 |

41 |

42 |

#include <phpcpp.h>
43 | 
44 | // function that we're going to export
45 | void myFunction()
46 | {
47 | }
48 | 
49 | extern "C" {
50 |     PHPCPP_EXPORT void *get_module() {
51 |         
52 |         // create extension object
53 |         static Php::Extension extension("my_extension", "1.0");
54 |         
55 |         // create a namespace
56 |         Php::Namespace myNamespace("myNamespace");
57 |         
58 |         // add the myFunction function to the namespace
59 |         myNamespace.add("myFunction", myFunction);
60 |         
61 |         // @todo add more functions and classes to the namespace
62 |         
63 |         // create a nested namespace
64 |         Php::Namespace nestedNamespace("nestedNamespace");
65 |         
66 |         // @todo add functions and classes to the nested namespace
67 |         
68 |         // add the nested namespace to the first namespace
69 |         myNamespace.add(std::move(nestedNamespace));
70 |         
71 |         // add the namespace to the extension
72 |         extension.add(std::move(myNamespace));
73 |         
74 |         // return the extension
75 |         return extension;
76 |     }
77 | }
78 |

79 |

80 | The Php::Namespace class is just a container that automatically adds a 81 | prefix to all classes and functions that you add to it. Nesting namespaces 82 | is possible too, as you saw in the example. 83 |

84 |

85 | In the example we used the std::move() function to move the nested namespace 86 | into the parent namespace, and to move the first namespace into the extension. 87 | Moving is more efficient that adding, although a regular extension.add(myNamespace) 88 | would have been valid too. 89 |

90 | -------------------------------------------------------------------------------- /include/array.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Array.h 3 | * 4 | * The Array is a wrapper around the value class that ensures that a 5 | * certain property always is an array 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 - 2019 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Class definition 18 | */ 19 | class PHPCPP_EXPORT Array : public Value 20 | { 21 | public: 22 | /** 23 | * Constructor 24 | */ 25 | Array() : Value(Type::Array) {} 26 | 27 | /** 28 | * Copy constructor from a value object 29 | * @param value 30 | */ 31 | Array(const Value &value) : Value(value) 32 | { 33 | // type must be valid 34 | if (value.type() != Type::Array) throw Error("Assigning a non-array to an array variable"); 35 | } 36 | 37 | /** 38 | * Move constructor from a value object 39 | * @param value 40 | */ 41 | Array(Value &&value) : Value(std::move(value)) 42 | { 43 | // type must be valid 44 | if (value.type() != Type::Array) throw Error("Moving a non-array to an array variable"); 45 | } 46 | 47 | /** 48 | * Constructors from a vector (this will create an array) 49 | * @param value 50 | */ 51 | template 52 | Array(const std::vector &input) : Value(input) {} 53 | 54 | /** 55 | * Constructor from a map (this will create an associative array) 56 | * @param value 57 | */ 58 | template 59 | Array(const std::map &value) : Value(value) {} 60 | 61 | // old visual c++ environments have no support for initializer lists 62 | # if !defined(_MSC_VER) || _MSC_VER >= 1800 63 | 64 | /** 65 | * Constructor from an initializer list 66 | * @param value 67 | */ 68 | Array(const std::initializer_list &value) : Value(value) {} 69 | 70 | // end of visual c++ check 71 | # endif 72 | 73 | /** 74 | * Destructor 75 | */ 76 | virtual ~Array() {} 77 | 78 | /** 79 | * Change the internal type of the variable 80 | * @param Type 81 | */ 82 | virtual Value &setType(Type type) & override 83 | { 84 | // throw exception if things are going wrong 85 | if (type != Type::Array) throw Error("Changing type of a fixed array variable"); 86 | 87 | // call base 88 | return Value::setType(Type::Array); 89 | } 90 | 91 | /** 92 | * Assignment operator 93 | * @param value 94 | * @return Array 95 | */ 96 | Array &operator=(const Value &value) 97 | { 98 | // skip self assignment 99 | if (this == &value) return *this; 100 | 101 | // type must be valid 102 | if (value.type() != Type::Array) throw Error("Assigning a non-array to a fixed array variable"); 103 | 104 | // call base 105 | Value::operator=(value); 106 | 107 | // done 108 | return *this; 109 | } 110 | 111 | /** 112 | * Move assignment operator 113 | * @param value 114 | * @return Array 115 | */ 116 | Array &operator=(Value &&value) 117 | { 118 | // skip self assignment 119 | if (this == &value) return *this; 120 | 121 | // type must be valid 122 | if (value.type() != Type::Array) throw Error("Moving a non-array to a fixed array variable"); 123 | 124 | // call base 125 | Value::operator=(std::move(value)); 126 | 127 | // done 128 | return *this; 129 | } 130 | }; 131 | 132 | /** 133 | * End of namespace 134 | */ 135 | } 136 | -------------------------------------------------------------------------------- /include/arrayaccess.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ArrayAccess.h 3 | * 4 | * "Interface" that can be "implemented" by your class. If you do, you 5 | * create your class like this: 6 | * 7 | * class MyClass : public Php::Base, public Php::ArrayAccess { ... } 8 | * 9 | * @author Emiel Bruijntjes 10 | * @copyright 2014 Copernica BV 11 | */ 12 | 13 | /** 14 | * Set up namespace 15 | */ 16 | namespace Php { 17 | 18 | /** 19 | * Class definition 20 | */ 21 | class PHPCPP_EXPORT ArrayAccess 22 | { 23 | public: 24 | /** 25 | * Check if a member is set 26 | * @param key 27 | * @return bool 28 | */ 29 | virtual bool offsetExists(const Php::Value &key) = 0; 30 | 31 | /** 32 | * Set a member 33 | * @param key 34 | * @param value 35 | */ 36 | virtual void offsetSet(const Php::Value &key, const Php::Value &value) = 0; 37 | 38 | /** 39 | * Retrieve a member 40 | * @param key 41 | * @return value 42 | */ 43 | virtual Php::Value offsetGet(const Php::Value &key) = 0; 44 | 45 | /** 46 | * Remove a member 47 | * @param key 48 | */ 49 | virtual void offsetUnset(const Php::Value &key) = 0; 50 | 51 | /** 52 | * Destructor 53 | */ 54 | virtual ~ArrayAccess() = default; 55 | }; 56 | 57 | /** 58 | * End namespace 59 | */ 60 | } 61 | -------------------------------------------------------------------------------- /include/byref.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ByRef.h 3 | * 4 | * Overridden Argument class to specify by-reference function arguments 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class PHPCPP_EXPORT ByRef : public Argument 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the argument 24 | * @param type Argument type 25 | * @param required Is this argument required? 26 | */ 27 | ByRef(const char *name, Type type = Type::Null, bool required = true) : Argument(name, type, required, true) {} 28 | 29 | /** 30 | * Constructor 31 | * @param name Name of the argument 32 | * @param classname Name of the class 33 | * @param nullable Can it be null? 34 | * @param required Is this argument required? 35 | */ 36 | ByRef(const char *name, const char *classname, bool nullable = false, bool required = true) : Argument(name, classname, nullable, required, true) {} 37 | 38 | /** 39 | * Copy constructor 40 | * @param argument 41 | */ 42 | ByRef(const ByRef &argument) : Argument(argument) {} 43 | 44 | /** 45 | * Move constructor 46 | * @param argument 47 | */ 48 | ByRef(ByRef &&argument) _NOEXCEPT : Argument(argument) {} 49 | 50 | /** 51 | * Destructor 52 | */ 53 | virtual ~ByRef() {} 54 | }; 55 | 56 | /** 57 | * End of namespace 58 | */ 59 | } 60 | -------------------------------------------------------------------------------- /include/byval.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ByVal.h 3 | * 4 | * Overridden Argument class to specify by-value function arguments 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class PHPCPP_EXPORT ByVal : public Argument 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the argument 24 | * @param type Argument type 25 | * @param required Is this argument required? 26 | */ 27 | ByVal(const char *name, Type type = Type::Null, bool required = true) : Argument(name, type, required, false) {} 28 | 29 | /** 30 | * Constructor 31 | * @param name Name of the argument 32 | * @param classname Name of the class 33 | * @param nullable Can it be null? 34 | * @param required Is this argument required? 35 | */ 36 | ByVal(const char *name, const char *classname, bool nullable = false, bool required = true) : Argument(name, classname, nullable, required, false) {} 37 | 38 | /** 39 | * Copy constructor 40 | * @param argument 41 | */ 42 | ByVal(const ByVal &argument) : Argument(argument) {} 43 | 44 | /** 45 | * Move constructor 46 | * @param argument 47 | */ 48 | ByVal(ByVal &&argument) _NOEXCEPT : Argument(argument) {} 49 | 50 | /** 51 | * Destructor 52 | */ 53 | virtual ~ByVal() {} 54 | }; 55 | 56 | /** 57 | * End of namespace 58 | */ 59 | } 60 | -------------------------------------------------------------------------------- /include/classtype.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file classtype.h 3 | * 4 | * Internal class types enumeration. 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 - 2022 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Enumeration declaration 17 | * The definition of the variables can be found in the Zend directory, 18 | * so that we can use the macro's from the PHP header files. 19 | */ 20 | enum class ClassType; 21 | 22 | /** 23 | * End namespace 24 | */ 25 | } 26 | -------------------------------------------------------------------------------- /include/countable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Countable.h 3 | * 4 | * "Interface" that can be "implemented" by your class. If you do, you 5 | * create your class like this: 6 | * 7 | * class MyClass : public Php::Base, public Php::Countable { ... } 8 | * 9 | * You will have to implement the count() method, which should return the 10 | * number of elements in the object 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2014 Copernica BV 14 | */ 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class PHPCPP_EXPORT Countable 25 | { 26 | public: 27 | /** 28 | * Retrieve the number of items in the class 29 | * @return long 30 | */ 31 | virtual long count() = 0; 32 | 33 | }; 34 | 35 | /** 36 | * End namespace 37 | */ 38 | } 39 | -------------------------------------------------------------------------------- /include/deprecated.h: -------------------------------------------------------------------------------- 1 | /** 2 | * deprecated.h 3 | * 4 | * This file defines macros to mark a function as deprecated 5 | * in a way that works across different compilers. 6 | * 7 | * It is used for functions that still work, but should no 8 | * longer be used because they may be removed in an upcoming 9 | * version of PHP-CPP 10 | * 11 | * @copyright 2016 Copernica B.V. 12 | */ 13 | 14 | #if __cplusplus >= 201402L 15 | #define PHPCPP_DEPRECATED [[deprecated]] 16 | #elif defined __GNUC__ 17 | #define PHPCPP_DEPRECATED __attribute__((deprecated)) 18 | #elif defined(_MSC_VER) 19 | #define PHPCPP_DEPRECATED __declspec(deprecated) 20 | #endif 21 | -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Error.h 3 | * 4 | * Class for fatal programming errors. You should normally not catch 5 | * these exceptions, but let them bubble up to crash your script, but 6 | * if you insist, you can. 7 | * 8 | * In your C++ extension you can both throw and catch instances of these 9 | * class. If you throw an exception, it will bubble up to PHP space, 10 | * where the PHP script can then catch it. 11 | * 12 | * Error thrown from PHP space can also be caught in C++ code. 13 | * If you put your call to a PHP user space function inside a try-catch 14 | * block, you can catch the exceptions as Php::Error objects. 15 | * 16 | * @author Emiel Bruijntjes 17 | * @copyright 2019 Copernica BV 18 | */ 19 | 20 | /** 21 | * Begin of namespace 22 | */ 23 | namespace Php { 24 | 25 | /** 26 | * Class definition 27 | */ 28 | class PHPCPP_EXPORT Error : public Throwable 29 | { 30 | protected: 31 | /** 32 | * Internal constructor to wrap around an exception object 33 | * @param object 34 | */ 35 | Error(struct _zend_object *object) : Throwable(object) {} 36 | 37 | /** 38 | * Rethrow the exception / make sure that it ends up in PHP space 39 | */ 40 | virtual void rethrow() override; 41 | 42 | public: 43 | /** 44 | * Public constructor 45 | * @param message 46 | */ 47 | Error(const std::string &message) : Throwable(message) {} 48 | 49 | /** 50 | * Destructor 51 | */ 52 | virtual ~Error() = default; 53 | }; 54 | 55 | /** 56 | * End of namespace 57 | */ 58 | } 59 | 60 | -------------------------------------------------------------------------------- /include/exception.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Exception.h 3 | * 4 | * Class for runtime errors. In your C++ extension you can both throw 5 | * and catch instances of these class. If you throw an exception, it 6 | * will bubble up to PHP space, where the PHP script can then catch it. 7 | * 8 | * Exceptions called from PHP space can also be caught in C++ code. 9 | * If you put your call to a PHP user space function inside a try-catch 10 | * block, you can catch the exceptions as Php::Exception objects. 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2019 Copernica BV 14 | */ 15 | 16 | /** 17 | * Begin of namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class PHPCPP_EXPORT Exception : public Throwable 25 | { 26 | protected: 27 | /** 28 | * Internal constructor to wrap around an exception object 29 | * @param object 30 | */ 31 | Exception(struct _zend_object *object) : Throwable(object) {} 32 | 33 | /** 34 | * Rethrow the exception / make sure that it ends up in PHP space 35 | */ 36 | virtual void rethrow() override; 37 | 38 | public: 39 | /** 40 | * Public constructor 41 | * @param message 42 | */ 43 | Exception(const std::string &message) : Throwable(message) {} 44 | 45 | /** 46 | * Destructor 47 | */ 48 | virtual ~Exception() = default; 49 | }; 50 | 51 | /** 52 | * End of namespace 53 | */ 54 | } 55 | 56 | -------------------------------------------------------------------------------- /include/file.h: -------------------------------------------------------------------------------- 1 | /** 2 | * File.h 3 | * 4 | * Extended script, a PHP source file name can be passed to a Php::File object 5 | * to have it evaluated. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2014 Copernica BV 9 | */ 10 | 11 | /** 12 | * Forward declarations 13 | */ 14 | struct _zend_string; 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class PHPCPP_EXPORT File 25 | { 26 | public: 27 | /** 28 | * Constructor 29 | * 30 | * The constructor receives a filename as parameter. It uses the normal 31 | * PHP include path resolve algorithms to find the location of the file. 32 | * 33 | * @param name the filename 34 | * @param size size of the filename 35 | */ 36 | File(const char *name, size_t size); 37 | 38 | /** 39 | * Alternative constructor with just a filename 40 | * 41 | * @param name the filename 42 | */ 43 | File(const char *name) : File(name, ::strlen(name)) {} 44 | 45 | /** 46 | * Alternative constructor with a string object 47 | * @param name the filename 48 | */ 49 | File(const std::string &name) : File(name.c_str(), name.size()) {} 50 | 51 | /** 52 | * Alternative constructor with a Value object 53 | * @param name the filename 54 | */ 55 | File(const Value &value) : File(value.stringValue()) {} 56 | 57 | /** 58 | * Destructor 59 | */ 60 | virtual ~File(); 61 | 62 | /** 63 | * Does the file exist? 64 | * @return boolean 65 | */ 66 | bool exists(); 67 | 68 | /** 69 | * Is this a valid file? 70 | * @return boolean 71 | */ 72 | bool valid(); 73 | 74 | /** 75 | * Execute the file once (do nothing if the file already was executed) 76 | * @return Php::Value 77 | */ 78 | Value once(); 79 | 80 | /** 81 | * Execute the file 82 | * @return Php::Value 83 | */ 84 | Value execute(); 85 | 86 | private: 87 | /** 88 | * The original path 89 | * @var struct _zend_string* 90 | */ 91 | struct _zend_string *_original = nullptr; 92 | 93 | /** 94 | * The full resolved path name 95 | * @var struct _zend_string* 96 | */ 97 | struct _zend_string *_path = nullptr; 98 | 99 | /** 100 | * The opcodes of this file 101 | * @var std::unique_ptr 102 | */ 103 | std::unique_ptr _opcodes; 104 | 105 | /** 106 | * Compile the file 107 | * @return bool 108 | */ 109 | bool compile(); 110 | 111 | }; 112 | 113 | /** 114 | * End of namespace 115 | */ 116 | } 117 | -------------------------------------------------------------------------------- /include/function.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Function.h 3 | * 4 | * Small extension to the Value class that allows a value to be 5 | * constructed with a std::function. 6 | * 7 | * If you want to assign a std::function to a value, the following 8 | * piece of code won't work: 9 | * 10 | * Php::Value value([]() { .... }); 11 | * 12 | * Because the passed in function would match with many of the possible 13 | * Value constructors. For that reason we have created a small and 14 | * simple Function class that can be used instead: 15 | * 16 | * Php::Function valu([]() { .... }); 17 | * 18 | * A Php::Function is an extended Php::Value object, so can be used 19 | * in place of Php::Values all the time. The only difference is that 20 | * it has a different constructor 21 | * 22 | * @author Emiel Bruijntjes 23 | * @copyright 2015 Copernica BV 24 | */ 25 | 26 | /** 27 | * Set up namespace 28 | */ 29 | namespace Php { 30 | 31 | /** 32 | * Class definition 33 | */ 34 | class PHPCPP_EXPORT Function : public Value 35 | { 36 | public: 37 | /** 38 | * Constructor to wrap a function that takes parameters 39 | * @param function The C++ function to be wrapped 40 | */ 41 | Function(const std::function &function); 42 | 43 | /** 44 | * Constructor to wrap a function that does not accept parameters 45 | * 46 | * Old C++ compilers do not see a difference between std::function 47 | * objects based on the function signature, so these old compilers 48 | * do not see this method. 49 | * 50 | * @param function The C++ function to be wrapped 51 | */ 52 | #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) || __clang__ 53 | Function(const std::function &function) : Function([function](Parameters ¶ms) -> Value { 54 | 55 | // call original function, forget about the parameters 56 | return function(); 57 | 58 | }) {} 59 | #endif 60 | 61 | /** 62 | * Destructor 63 | */ 64 | virtual ~Function() {} 65 | 66 | private: 67 | /** 68 | * Retrieve the class entry of the _functor class 69 | * @return _zend_class_entry 70 | */ 71 | static struct _zend_class_entry *entry(); 72 | 73 | 74 | }; 75 | 76 | /** 77 | * End namespace 78 | */ 79 | } 80 | -------------------------------------------------------------------------------- /include/globals.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Globals.h 3 | * 4 | * Wrapper object that gives access to all global variables. You 5 | * can use it more or less the same as the $_GLOBALS object in 6 | * PHP. 7 | * 8 | * The global PHP variables are acessible via the Php::globals["varname"] 9 | * variables. 10 | * 11 | * @author Emiel Bruijntjes 12 | * @copyright 2013 Copernica BV 13 | */ 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Forward definitions 22 | */ 23 | class Global; 24 | 25 | /** 26 | * Class definition 27 | */ 28 | class PHPCPP_EXPORT Globals 29 | { 30 | public: 31 | /** 32 | * Disable copy and move operations 33 | */ 34 | Globals(const Globals &globals) = delete; 35 | Globals(Globals &&globals) = delete; 36 | 37 | /** 38 | * Destructor 39 | */ 40 | virtual ~Globals() {} 41 | 42 | /** 43 | * Get access to a global variable 44 | * @param name 45 | * @return Global 46 | */ 47 | Global operator[](const char *name); 48 | 49 | /** 50 | * Get access to a global variable 51 | * @param name 52 | * @return Global 53 | */ 54 | Global operator[](const std::string &name); 55 | 56 | private: 57 | /** 58 | * Constructor 59 | */ 60 | Globals() {} 61 | 62 | public: 63 | /** 64 | * Get the one and only instance 65 | * @return Globals 66 | */ 67 | static Globals &instance(); 68 | }; 69 | 70 | /** 71 | * We always have one instance of the GLOBALS instance 72 | * @var Globals 73 | */ 74 | extern PHPCPP_EXPORT Globals &GLOBALS; 75 | 76 | /** 77 | * End of namespace 78 | */ 79 | } 80 | -------------------------------------------------------------------------------- /include/hashparent.h: -------------------------------------------------------------------------------- 1 | /** 2 | * HashParent.h 3 | * 4 | * Interface that is implemented by all objects that can be accessed with 5 | * array-access variables ([]). When the value of a hash-member is changed, 6 | * it will call one of the methods from this class to set the new property 7 | * 8 | * This is an internal class that you normally not need when writing 9 | * extensions. It is used by the PHP-CPP library when you use constructs 10 | * like value["x"]["y"] = 10; 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2014 Copernica BV 14 | */ 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Forwards 23 | */ 24 | class Value; 25 | 26 | /** 27 | * Class definition 28 | */ 29 | class PHPCPP_EXPORT HashParent 30 | { 31 | protected: 32 | /** 33 | * Protected constructor - users should not instantiate HashParent 34 | * objects themselved. Use a Value object instead. 35 | */ 36 | HashParent() {} 37 | 38 | public: 39 | /** 40 | * Destructor 41 | */ 42 | virtual ~HashParent() {} 43 | 44 | /** 45 | * Check if a certain key exists in the array/object 46 | * @param key 47 | * @return bool 48 | */ 49 | virtual bool contains(const std::string &key) const = 0; 50 | 51 | /** 52 | * Check if a certain index exists in the array/object 53 | * @param key 54 | * @return bool 55 | */ 56 | virtual bool contains(int index) const = 0; 57 | 58 | /** 59 | * Check if a certain index exists in the array/object 60 | * @param key 61 | * @return bool 62 | */ 63 | virtual bool contains(const Value &index) const = 0; 64 | 65 | /** 66 | * Retrieve the value at a string index 67 | * @param key 68 | * @return Value 69 | */ 70 | virtual Value get(const std::string &key) const = 0; 71 | 72 | /** 73 | * Retrieve the value at a numeric index 74 | * @param index 75 | * @return Value 76 | */ 77 | virtual Value get(int index) const = 0; 78 | 79 | /** 80 | * Retrieve the value at a value index 81 | * @param key 82 | * @return Value 83 | */ 84 | virtual Value get(const Value &key) const = 0; 85 | 86 | /** 87 | * Overwrite the value at a certain string index 88 | * @param key 89 | * @param value 90 | */ 91 | virtual void set(const std::string &key, const Value &value) = 0; 92 | 93 | /** 94 | * Overwrite the value at a certain numeric index 95 | * @param index 96 | * @param value 97 | */ 98 | virtual void set(int index, const Value &value) = 0; 99 | 100 | /** 101 | * Overwrite the value at a certain variant index 102 | * @param key 103 | * @param value 104 | */ 105 | virtual void set(const Value &key, const Value &value) = 0; 106 | 107 | /** 108 | * Unset a member by its index 109 | * @param index 110 | */ 111 | virtual void unset(int index) = 0; 112 | 113 | /** 114 | * Unset a member by its key 115 | * @param key 116 | */ 117 | virtual void unset(const std::string &key) = 0; 118 | 119 | /** 120 | * Unset a member by its key 121 | * @param key 122 | */ 123 | virtual void unset(const Value &key) = 0; 124 | 125 | }; 126 | 127 | /** 128 | * End namespace 129 | */ 130 | } 131 | -------------------------------------------------------------------------------- /include/inivalue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * IniValue.h 3 | * 4 | * Class IniValue designed for extracting values from ini entries 5 | * 6 | * @copyright 2014 Copernica BV 7 | */ 8 | 9 | /** 10 | * Set up namespace 11 | */ 12 | namespace Php { 13 | 14 | /** 15 | * Class IniValue designed for extracting values from ini entries. 16 | */ 17 | class PHPCPP_EXPORT IniValue 18 | { 19 | public: 20 | /** 21 | * Constructors 22 | * 23 | * @param name Name of the php.ini variable 24 | * @param isorig Is the original value 25 | */ 26 | IniValue(const char *name, const bool isorig) : _name(name), _isorig(isorig) {} 27 | 28 | /** 29 | * Cast to a 16-bit number 30 | * @return int16_t 31 | */ 32 | operator int16_t () const 33 | { 34 | return static_cast(numericValue()); 35 | } 36 | 37 | /** 38 | * Cast to a 32-bit number 39 | * @return int32_t 40 | */ 41 | operator int32_t () const 42 | { 43 | return static_cast(numericValue()); 44 | } 45 | 46 | /** 47 | * Cast to a 64-bit number 48 | * @return uint64_t 49 | */ 50 | operator int64_t () const 51 | { 52 | return numericValue(); 53 | } 54 | 55 | /** 56 | * Cast to a boolean 57 | * @return boolean 58 | */ 59 | operator bool () const 60 | { 61 | return boolValue(); 62 | } 63 | 64 | /** 65 | * Cast to a string 66 | * @return string 67 | */ 68 | operator std::string () const 69 | { 70 | return stringValue(); 71 | } 72 | 73 | /** 74 | * Cast to byte array 75 | * @return const char * 76 | */ 77 | operator const char * () const 78 | { 79 | return rawValue(); 80 | } 81 | 82 | /** 83 | * Cast to a floating point 84 | * @return double 85 | */ 86 | operator double() const; 87 | 88 | /** 89 | * Retrieve the value as number 90 | * 91 | * We force this to be a int64_t because we assume that most 92 | * servers run 64 bits nowadays, and because we use int32_t, int64_t 93 | * almost everywhere, instead of 'long' and on OSX neither of 94 | * these intxx_t types is defined as 'long'... 95 | * 96 | * @return int64_t 97 | */ 98 | int64_t numericValue() const; 99 | 100 | /** 101 | * Boolean value 102 | * @return bool 103 | */ 104 | bool boolValue() const 105 | { 106 | return static_cast(numericValue()); 107 | } 108 | 109 | /** 110 | * String value 111 | * @return std::string 112 | */ 113 | std::string stringValue() const 114 | { 115 | auto value = rawValue(); 116 | return std::string(value ? value : ""); 117 | } 118 | 119 | /** 120 | * Get access to the raw buffer for read operations. 121 | * @return const char * 122 | */ 123 | const char *rawValue() const; 124 | 125 | 126 | private: 127 | 128 | 129 | /** 130 | * ini entry name 131 | * @var std::string 132 | */ 133 | std::string _name; 134 | 135 | /** 136 | * Is the orig value? 137 | * @var bool 138 | */ 139 | bool _isorig = false; 140 | }; 141 | 142 | /** 143 | * Custom output stream operator 144 | * @param stream 145 | * @param ini_val 146 | * @return ostream 147 | */ 148 | PHPCPP_EXPORT std::ostream &operator<<(std::ostream &stream, const IniValue &ini_val); 149 | 150 | 151 | /** 152 | * End of namespace 153 | */ 154 | } 155 | -------------------------------------------------------------------------------- /include/interface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface.h 3 | * 4 | * @copyright 2014 - 2022 Copernica BV 5 | * @author Emiel Bruijntjes 6 | */ 7 | 8 | /** 9 | * Set up namespace 10 | */ 11 | namespace Php { 12 | 13 | /** 14 | * Class definition 15 | */ 16 | class PHPCPP_EXPORT Interface : private ClassBase 17 | { 18 | public: 19 | /** 20 | * Constructor 21 | * @param name 22 | */ 23 | Interface(const char *name); 24 | 25 | /** 26 | * Destructor 27 | */ 28 | virtual ~Interface() = default; 29 | 30 | /** 31 | * Add a - of course abstract - method to the interface 32 | * @param name Name of the method 33 | * @param arguments Optional description of the arguments 34 | * @return Interface Same object to allow chaining 35 | */ 36 | Interface &method(const char *name, const Arguments &arguments = {}) 37 | { 38 | // call base 39 | ClassBase::method(name, Abstract | Public, arguments); 40 | 41 | // return self 42 | return *this; 43 | } 44 | 45 | /** 46 | * Add a - of course abstract - method to the interface 47 | * @param name Name of the method 48 | * @param flags Optional flags 49 | * @param arguments Optional description of the arguments 50 | * @return Interface Same object to allow chaining 51 | */ 52 | Interface &method(const char *name, int flags, const Arguments &arguments = {}) 53 | { 54 | // call base (an interface method is always public, so we add these flags, 55 | // and although it is always abstract, PHP does not allow this flag, so we 56 | // remove it in case the extension programmer had set it) 57 | ClassBase::method(name, (Public | flags) & ~Abstract, arguments); 58 | 59 | // return self 60 | return *this; 61 | } 62 | 63 | /** 64 | * Extends exisiting PHP interface 65 | * 66 | * Note that the interface that you supply must already exist! Therefore 67 | * you can only supply interfaces that you created in your own extension. 68 | * 69 | * @param interface Interface object 70 | * @return Interface Same object to allow chaining 71 | */ 72 | Interface &extends(const Interface &interface) { ClassBase::implements(interface); return *this; } 73 | 74 | /** 75 | * The namespace needs to have access to the private ClassBase base 76 | * class, to actually register the interface. 77 | */ 78 | friend class Namespace; 79 | 80 | /** 81 | * All Php::Class also need access to the base class to 82 | * register an interface. 83 | */ 84 | template friend class Class; 85 | }; 86 | 87 | /** 88 | * End namespace 89 | */ 90 | } 91 | -------------------------------------------------------------------------------- /include/iterator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Iterator.h 3 | * 4 | * Base class for iterators. Extension writers that want to create traversable 5 | * classes, should override the Php::Traversable base class. This base class 6 | * forces you to implement a getIterator() method that returns an instance of 7 | * a Php::Iterator class. 8 | * 9 | * In this file you find the signature of the Php::Iterator class. It mostly has 10 | * pure virtual methods, which means that you should create a derived class 11 | * that implements all these methods. 12 | * 13 | * @author Emiel Bruijntjes 14 | * @copyright 2014 Copernica BV 15 | */ 16 | 17 | /** 18 | * Set up namespace 19 | */ 20 | namespace Php { 21 | 22 | /** 23 | * Class definition 24 | */ 25 | class PHPCPP_EXPORT Iterator 26 | { 27 | public: 28 | /** 29 | * Constructor 30 | * @param base Class over which the iterator is iterating 31 | */ 32 | Iterator(Base *base) : _object(base) {} 33 | 34 | /** 35 | * Destructor 36 | */ 37 | virtual ~Iterator() {} 38 | 39 | /** 40 | * Is the iterator on a valid position 41 | * @return bool 42 | */ 43 | virtual bool valid() = 0; 44 | 45 | /** 46 | * The value at the current position 47 | * @return Value 48 | */ 49 | virtual Value current() = 0; 50 | 51 | /** 52 | * The key at the current position 53 | * @return Value 54 | */ 55 | virtual Value key() = 0; 56 | 57 | /** 58 | * Move to the next position 59 | */ 60 | virtual void next() = 0; 61 | 62 | /** 63 | * Rewind the iterator to the front position 64 | */ 65 | virtual void rewind() = 0; 66 | 67 | protected: 68 | /** 69 | * During the lifetime of the iterator, the object over which 70 | * it iterates is keps as a private variable. This ensures that 71 | * this object is not destructed as long as the iterator exists 72 | * @var Value 73 | */ 74 | Value _object; 75 | 76 | }; 77 | 78 | /** 79 | * End namespace 80 | */ 81 | } 82 | -------------------------------------------------------------------------------- /include/message.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Message.h 3 | * 4 | * In this file an enumeration type is defined with all error-message flags. 5 | * 6 | * @author Toon Schoenmakers 7 | * @copyright 2015 - 2019 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Supported types of errors, this is mostly a copy from Zend/zend_errors.h 17 | */ 18 | enum class Message : int { 19 | Error = (1 << 0L), 20 | Warning = (1 << 1L), 21 | Parse = (1 << 2L), 22 | Notice = (1 << 3L), 23 | CoreError = (1 << 4L), 24 | CoreWarning = (1 << 5L), 25 | CompileError = (1 << 6L), 26 | CompileWarning = (1 << 7L), 27 | UserError = (1 << 8L), 28 | UserWarning = (1 << 9L), 29 | UserNotice = (1 << 10L), 30 | Strict = (1 << 11L), 31 | RecoverableError = (1 << 12L), 32 | Deprecated = (1 << 13L), 33 | UserDeprecated = (1 << 14L), 34 | 35 | Core = (CoreError | CoreWarning), 36 | All = (Error | Warning | Parse | Notice | CoreError | CoreWarning | CompileError | CompileWarning | UserError | UserWarning | UserNotice | RecoverableError | Deprecated | UserDeprecated ) 37 | }; 38 | 39 | /** 40 | * End of namespace 41 | */ 42 | } 43 | -------------------------------------------------------------------------------- /include/modifiers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Modifiers.h 3 | * 4 | * In this file an enumeration type is with the possible 5 | * member modifiers 6 | * 7 | * @author Martijn Otto 8 | * @copyright 2014 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * The modifiers are constants 18 | */ 19 | extern PHPCPP_EXPORT const int Static; 20 | extern PHPCPP_EXPORT const int Abstract; 21 | extern PHPCPP_EXPORT const int Final; 22 | extern PHPCPP_EXPORT const int Public; 23 | extern PHPCPP_EXPORT const int Protected; 24 | extern PHPCPP_EXPORT const int Private; 25 | extern PHPCPP_EXPORT const int Const; 26 | 27 | /** 28 | * Modifiers that are supported for methods and properties 29 | */ 30 | extern PHPCPP_EXPORT const int MethodModifiers; 31 | extern PHPCPP_EXPORT const int PropertyModifiers; 32 | 33 | /** 34 | * End namespace 35 | */ 36 | } 37 | -------------------------------------------------------------------------------- /include/noexcept.h: -------------------------------------------------------------------------------- 1 | /** 2 | * NoExcept.h 3 | * 4 | * Some compilers (hello microsoft!) do not yet support the "noexcept" 5 | * keyword. To overcome this, we use a macro that expands to "noexcept" 6 | * 7 | * @author Emiel Bruijntjes 8 | * @author atvive 9 | */ 10 | 11 | /** 12 | * Macro to be able to support MSVC compiler 13 | */ 14 | #ifndef _NOEXCEPT 15 | # ifndef _MSC_VER 16 | # define _NOEXCEPT noexcept 17 | # else 18 | # define _NOEXCEPT __declspec(nothrow) 19 | # endif 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /include/parameters.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameters.h 3 | * 4 | * Wrapper around parameters that are passed to a 5 | 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Forward declarations 17 | */ 18 | class Base; 19 | 20 | /** 21 | * Class definition 22 | */ 23 | class PHPCPP_EXPORT Parameters : public std::vector 24 | { 25 | private: 26 | /** 27 | * The base object 28 | * @var Base 29 | */ 30 | Base *_object = nullptr; 31 | 32 | protected: 33 | /** 34 | * Protected constructor 35 | * 36 | * The constructor is protected because extension programmers are not 37 | * supposed to instantiate parameters objects themselves 38 | * 39 | * @param object The 'this' object 40 | */ 41 | Parameters(Base *object) : _object(object) {} 42 | 43 | public: 44 | /** 45 | * Do _not_ add a virtual destructor here. 46 | * 47 | * We are extending a vector, which does not itself 48 | * have a virtual destructor, so destructing through 49 | * a pointer to this vector has no effect. 50 | * 51 | * By adding a virtual destructor we create a vtable, 52 | * which makes the class bigger, causing slicing and 53 | * then we are actually introducing the problem that 54 | * we are trying to avoid! 55 | */ 56 | 57 | /** 58 | * The object that is being called 59 | * @return Base 60 | */ 61 | Base *object() const 62 | { 63 | return _object; 64 | } 65 | }; 66 | 67 | /** 68 | * End of namespace 69 | */ 70 | } 71 | -------------------------------------------------------------------------------- /include/platform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Platform.h 3 | * 4 | * Macro that we use to find out whether we run on 64bit or 32bit 5 | * platforms. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2015 Copernica BV 9 | */ 10 | 11 | // Check windows 12 | #if _WIN32 || _WIN64 13 | #if _WIN64 14 | #define PHPCPP_64BIT 15 | #else 16 | #define PHPCPP_32BIT 17 | #endif 18 | #endif 19 | 20 | // Check GCC and clang 21 | #if __GNUC__ || __clang__ 22 | #if __x86_64__ || __ppc64__ 23 | #define PHPCPP_64BIT 24 | #else 25 | #define PHPCPP_32BIT 26 | #endif 27 | #endif 28 | -------------------------------------------------------------------------------- /include/script.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Script.h 3 | * 4 | * Class that can be used to evaluate a PHP script in the current PHP context. 5 | * 6 | * The difference between directly calling eval() is that the script object 7 | * will first evaluate the string, and then it can be executed multiple times. 8 | * 9 | * @author Emiel Bruijntjes 10 | * @copyright 2014 Copernica BV 11 | */ 12 | 13 | /** 14 | * Forward declarations 15 | */ 16 | struct _zend_op_array; 17 | 18 | /** 19 | * Set up namespace 20 | */ 21 | namespace Php { 22 | 23 | /** 24 | * Forward declarations 25 | */ 26 | class Opcodes; 27 | 28 | /** 29 | * Class definition 30 | */ 31 | class PHPCPP_EXPORT Script 32 | { 33 | public: 34 | /** 35 | * Constructor 36 | * 37 | * The constructor will not throw any exceptions, even when invalid 38 | * PHP code is passed to it that can not be evaluated. You should call 39 | * the valid() to find out if the script was valid (could be parsed). 40 | * 41 | * @param name Name of the PHP script 42 | * @param source PHP source code to be evaluated 43 | * @param size Length of the source code 44 | */ 45 | Script(const char *name, const char *source, size_t size) _NOEXCEPT; 46 | 47 | /** 48 | * Alternative constructor without a size 49 | * @param name Name of the PHP script 50 | * @param source PHP source code to be evaluated 51 | */ 52 | Script(const char *name, const char *source) _NOEXCEPT : Script(name, source, ::strlen(source)) {} 53 | 54 | /** 55 | * Alternative constructor without a name 56 | * @param source PHP source code to be evaluated 57 | * @param size Length of the source code 58 | */ 59 | Script(const char *source, size_t size) _NOEXCEPT : Script("Unknown", source, size) {} 60 | 61 | /** 62 | * Alternative constructor without a name and without a size 63 | * @param source PHP source code to be evaluated 64 | */ 65 | Script(const char *source) _NOEXCEPT : Script("Unknown", source, ::strlen(source)) {} 66 | 67 | /** 68 | * Constructor based on a std::string 69 | * @param source PHP source code to be evaluated 70 | */ 71 | Script(const std::string &source) _NOEXCEPT : Script("Unknown", source.c_str(), source.size()) {} 72 | 73 | /** 74 | * Destructor 75 | */ 76 | virtual ~Script(); 77 | 78 | /** 79 | * Is the script a valid PHP script without syntax errors? 80 | * @return bool 81 | */ 82 | bool valid() const; 83 | 84 | /** 85 | * Execute the script 86 | * The return value of the script is returned 87 | * @return Value 88 | */ 89 | Value execute() const; 90 | 91 | private: 92 | /** 93 | * The opcodes 94 | * @var Opcodes 95 | */ 96 | Opcodes *_opcodes; 97 | 98 | /** 99 | * Helper function to compile the source code 100 | * @param name name of the script 101 | * @param script actual PHP code 102 | * @param size length of the string 103 | * @return opcodes 104 | */ 105 | static struct _zend_op_array *compile(const char *name, const char *phpcode, size_t size); 106 | 107 | }; 108 | 109 | /** 110 | * End of namespace 111 | */ 112 | } 113 | -------------------------------------------------------------------------------- /include/serializable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Serializable interface 3 | * 4 | * This interface can be implemented to make an object that can be passed to 5 | * the PHP serialize() and unserialize() methods. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2014 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Class definition 18 | */ 19 | class PHPCPP_EXPORT Serializable 20 | { 21 | public: 22 | /** 23 | * Method to serialize the object 24 | * 25 | * This method should return a string representation of the object that 26 | * can be passed to the unserialize() method and that will revive the object 27 | * 28 | * @return std::string 29 | */ 30 | virtual std::string serialize() = 0; 31 | 32 | /** 33 | * Unserialize the object 34 | * 35 | * This method is called as an alternative __construct() method to initialize 36 | * the object. The passed in string parameter in in the format earlier returned 37 | * by a call to serialize() 38 | * 39 | * @param input String to parse 40 | * @param size Size of the string 41 | */ 42 | virtual void unserialize(const char *input, size_t size) = 0; 43 | }; 44 | 45 | /** 46 | * End namespace 47 | */ 48 | } 49 | -------------------------------------------------------------------------------- /include/stream.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Stream.h 3 | * 4 | * PHP internally uses a "stream" concept. This is a complicated 5 | * abstraction layer for sockets and filedescriptors and other sources 6 | * from which data can be read and/or to which data can be sent. 7 | * 8 | * This Php::Stream class can be used to wrap around a value (if that 9 | * value contains a stream) to access stream-specific properties. This 10 | * class currently has a very limited API, but more features can be 11 | * added if needed. 12 | * 13 | * @author Emiel Bruijntjes 14 | * @copyright 2019 Copernica BV 15 | */ 16 | 17 | /** 18 | * Include guard 19 | */ 20 | #pragma once 21 | 22 | /** 23 | * Forward declaration 24 | */ 25 | struct _php_stream; 26 | 27 | /** 28 | * Begin of namespace 29 | */ 30 | namespace Php { 31 | 32 | /** 33 | * Class definition 34 | */ 35 | class PHPCPP_EXPORT Stream 36 | { 37 | private: 38 | /** 39 | * The wrapped value that is suppoed to hold a stream 40 | * @var Value 41 | */ 42 | Value _value; 43 | 44 | /** 45 | * Object holding the stream data 46 | * @var struct _php_stream 47 | */ 48 | struct _php_stream *_stream; 49 | 50 | public: 51 | /** 52 | * Constructor 53 | * @param value value to be wrapped 54 | * @throws std::runtime_error 55 | */ 56 | Stream(const Value &value); 57 | 58 | /** 59 | * No copying 60 | * @param that 61 | */ 62 | Stream(const Stream &that) = delete; 63 | 64 | /** 65 | * Destructor 66 | */ 67 | virtual ~Stream(); 68 | 69 | /** 70 | * Size of the read-buffer (number of bytes that have already been read 71 | * from the underlying filesystem, but that are not yet passed to php space) 72 | * @return size_t 73 | */ 74 | size_t readbuffer() const; 75 | 76 | /** 77 | * Get access to the internal filedescriptor 78 | * Note that not every stream is always associated with a filedescriptor, 79 | * in which case this function returns -1 80 | * @return int 81 | */ 82 | int fd() const; 83 | }; 84 | 85 | /** 86 | * End of namespace 87 | */ 88 | } 89 | 90 | -------------------------------------------------------------------------------- /include/streams.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Streams.h 3 | * 4 | * Just like the standard std::cout and std::cerr objects to output data, you 5 | * can use similar stream objects for outputting data to PHP. Php::out is the 6 | * C++ equivalent of the PHP echo() function, and Php::err() is the C++ stream 7 | * that behaves like calling trigger_error() from PHP. 8 | * 9 | * Php::out << "this is example text" << std::endl; 10 | * Php::err << "this is an error message" << std::endl; 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2014 Copernica BV 14 | */ 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Define the out and err objects 23 | */ 24 | extern thread_local PHPCPP_EXPORT std::ostream out; 25 | extern thread_local PHPCPP_EXPORT std::ostream error; 26 | extern thread_local PHPCPP_EXPORT std::ostream notice; 27 | extern thread_local PHPCPP_EXPORT std::ostream warning; 28 | extern thread_local PHPCPP_EXPORT std::ostream deprecated; 29 | 30 | /** 31 | * End namespace 32 | */ 33 | } 34 | 35 | -------------------------------------------------------------------------------- /include/super.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Super.h 3 | * 4 | * The Super class is used to implement one of the super variables $_POST, 5 | * $_GET, $_SERVER, et cetera 6 | * 7 | * @copyright 2014 Copernica BV 8 | * @author Emiel Bruijntjes 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Class definition 18 | */ 19 | class PHPCPP_EXPORT Super 20 | { 21 | public: 22 | /** 23 | * Constructor 24 | * 25 | * Extension writers do not have to access the super-globals themselves. 26 | * They are always accessible via Php::POST, Php::GET, et cetera. 27 | * 28 | * @param index index number 29 | * @param name name of the variable in PHP 30 | */ 31 | Super(int index, const char *name) : _index(index), _name(name) {} 32 | 33 | /** 34 | * Destructor 35 | */ 36 | virtual ~Super() {} 37 | 38 | /** 39 | * Array access operator 40 | * This can be used for accessing associative arrays 41 | * @param key 42 | * @return Value 43 | */ 44 | Value operator[](const std::string &key) 45 | { 46 | // convert object to a value object, and retrieve the key 47 | return value().get(key); 48 | } 49 | 50 | /** 51 | * Array access operator 52 | * This can be used for accessing associative arrays 53 | * @param key 54 | * @return Value 55 | */ 56 | Value operator[](const char *key) 57 | { 58 | // convert object to a value object, and retrieve the key 59 | return value().get(key); 60 | } 61 | 62 | /** 63 | * Casting operator to cast to a value object 64 | * @return Value 65 | */ 66 | operator Value () 67 | { 68 | // we have a private function for this 69 | return value(); 70 | } 71 | 72 | /** 73 | * Return an iterator for iterating over the variables 74 | * @return iterator 75 | */ 76 | ValueIterator begin() 77 | { 78 | // convert to value, and call begin on the value object 79 | return value().begin(); 80 | } 81 | 82 | /** 83 | * Return an iterator for iterating over the variables 84 | * @return iterator 85 | */ 86 | ValueIterator end() 87 | { 88 | // convert to value, and call end on that object 89 | return value().end(); 90 | } 91 | 92 | private: 93 | /** 94 | * Index number 95 | * @var int 96 | */ 97 | int _index; 98 | 99 | /** 100 | * Name of the variable in PHP 101 | * @var name 102 | */ 103 | const char *_name; 104 | 105 | /** 106 | * Turn the object into a value object 107 | * @return Value 108 | */ 109 | Value value(); 110 | 111 | }; 112 | 113 | /** 114 | * A number of super-globals are always accessible 115 | */ 116 | extern PHPCPP_EXPORT Super POST; 117 | extern PHPCPP_EXPORT Super GET; 118 | extern PHPCPP_EXPORT Super COOKIE; 119 | extern PHPCPP_EXPORT Super SERVER; 120 | extern PHPCPP_EXPORT Super ENV; 121 | extern PHPCPP_EXPORT Super FILES; 122 | extern PHPCPP_EXPORT Super REQUEST; 123 | 124 | /** 125 | * End namespace 126 | */ 127 | } 128 | -------------------------------------------------------------------------------- /include/thread_local.h: -------------------------------------------------------------------------------- 1 | /** 2 | * thread_local.h 3 | * 4 | * Some compilers claim to be C++11 compliant, yet fail to 5 | * implement basic features, such as the thread_local storage 6 | * specifier. These little cripples we help out a bit by 7 | * redefining the keyword to whatever proprietary cruft 8 | * they are using. 9 | * 10 | * @copyright 2016 Copernica B.V. 11 | */ 12 | 13 | // are we dealing with an outdated sort of compiler? 14 | #if defined(_MSC_VER) && _MSC_VER < 1500 15 | // can't use thread_local, but we can use their 16 | // limited storage scope specifier in this case 17 | #define thread_local __declspec( thread ) 18 | #endif 19 | -------------------------------------------------------------------------------- /include/throwable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Throwable.h 3 | * 4 | * Base class for exceptions and errors, where an error is a runtime 5 | * problem with the program (like file-does-not-exist), and an error 6 | * is a more fatal programming problem (like call-to-private-method). 7 | * 8 | * @author Jasper van Eck 9 | * @author Emiel Bruijntjes 10 | * @copyright 2013 - 2023 Copernica BV 11 | */ 12 | #include 13 | #include 14 | 15 | /** 16 | * Forward declarations 17 | */ 18 | struct _zend_object; 19 | 20 | /** 21 | * Set up namespace 22 | */ 23 | namespace Php { 24 | 25 | /** 26 | * Class definition 27 | */ 28 | class PHPCPP_EXPORT Throwable : public std::runtime_error 29 | { 30 | protected: 31 | /** 32 | * The exception code 33 | * @var long int 34 | */ 35 | long int _code = -1; 36 | 37 | 38 | protected: 39 | /** 40 | * Protected constructor - only derived classes can instantiate 41 | * @param message The exception message 42 | */ 43 | Throwable(const std::string &message) : std::runtime_error(message) {} 44 | 45 | /** 46 | * Another protected constructor 47 | * @param object 48 | */ 49 | Throwable(struct _zend_object *object); 50 | 51 | public: 52 | /** 53 | * Destructor 54 | */ 55 | virtual ~Throwable() = default; 56 | 57 | /** 58 | * Rethrow the exception / make sure that it ends up in PHP space 59 | */ 60 | virtual void rethrow() = 0; 61 | 62 | /** 63 | * Returns the exception code 64 | * @return The exception code 65 | */ 66 | long int code() const _NOEXCEPT 67 | { 68 | // expose the code 69 | return _code; 70 | } 71 | }; 72 | 73 | /** 74 | * End of namespace 75 | */ 76 | } 77 | -------------------------------------------------------------------------------- /include/traversable.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Traversable.h 3 | * 4 | * Interface that should be implemented by classes that want to be 5 | * traversable. A traversable objects can be iterated over in a PHP 6 | * foreach loop. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | 12 | /** 13 | * Set up namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Class definition 19 | */ 20 | class PHPCPP_EXPORT Traversable 21 | { 22 | public: 23 | /** 24 | * Retrieve an instance of the iterator 25 | * @return Iterator 26 | */ 27 | virtual Iterator *getIterator() = 0; 28 | }; 29 | 30 | /** 31 | * End namespace 32 | */ 33 | } 34 | -------------------------------------------------------------------------------- /include/type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Type.h 3 | * 4 | * In this file an enumeration type is defined with all supported variable 5 | * types. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Supported types for variables 18 | * The values are the same as the ones used internally in Zend 19 | */ 20 | enum class Type : unsigned char { 21 | Undefined = 0, // Variable is not set 22 | Null = 1, // Null will allow any type 23 | False = 2, // Boolean false 24 | True = 3, // Boolean true 25 | Numeric = 4, // Integer type 26 | Float = 5, // Floating point type 27 | String = 6, // A string obviously 28 | Array = 7, // An array of things 29 | Object = 8, // An object 30 | Resource = 9, // A resource 31 | Reference = 10, // Reference to another value (can be any type!) 32 | Constant = 11, // A constant value 33 | ConstantAST = 12, // I think an Abstract Syntax tree, not quite sure 34 | 35 | // "fake types", not quite sure what that means 36 | Bool = 13, // You will never get this back as a type 37 | Callable = 14, // I don't know why this is a "fake" type 38 | }; 39 | 40 | /** 41 | * End of namespace 42 | */ 43 | } 44 | -------------------------------------------------------------------------------- /include/valueiterator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ValueIterator.h 3 | * 4 | * This is an internal helper class that is used when iterating over a 5 | * Php::Value object - stl style. 6 | * 7 | * Thus, when you do c++ things like "for (auto &iter : value)", internally 8 | * a ValueIterator object is being used. 9 | * 10 | * @author Emiel Bruijntjes 11 | * @copyright 2014 Copernica BV 12 | */ 13 | 14 | /** 15 | * Set up namespace 16 | */ 17 | namespace Php { 18 | 19 | /** 20 | * Forward declarations 21 | */ 22 | class ValueIteratorImpl; 23 | 24 | /** 25 | * Class definition 26 | */ 27 | class PHPCPP_EXPORT ValueIterator 28 | { 29 | public: 30 | /** 31 | * Constructor 32 | * @param impl Implementation iterator 33 | */ 34 | ValueIterator(ValueIteratorImpl *impl); 35 | 36 | /** 37 | * Copy constructor 38 | * @param that 39 | */ 40 | ValueIterator(const ValueIterator &that); 41 | 42 | /** 43 | * Destructor 44 | */ 45 | virtual ~ValueIterator(); 46 | 47 | /** 48 | * Increment position (pre-increment) 49 | * @return ValueIterator 50 | */ 51 | ValueIterator &operator++(); 52 | 53 | /** 54 | * Increment position (post-increment) 55 | * @return ValueIterator 56 | */ 57 | ValueIterator operator++(int) 58 | { 59 | // make a copy 60 | ValueIterator copy(*this); 61 | 62 | // increment current object 63 | ++(*this); 64 | 65 | // and return the unchanged original 66 | return copy; 67 | } 68 | 69 | /** 70 | * Decrement position (pre-decrement) 71 | * @return ValueIterator 72 | */ 73 | ValueIterator &operator--(); 74 | 75 | /** 76 | * Increment position (post-decrement) 77 | * @return ValueIterator 78 | */ 79 | ValueIterator operator--(int) 80 | { 81 | // make a copy 82 | ValueIterator copy(*this); 83 | 84 | // decrement current object 85 | --(*this); 86 | 87 | // and return the unchanged original 88 | return copy; 89 | } 90 | 91 | /** 92 | * Compare with other iterator 93 | * @param that 94 | * @return bool 95 | */ 96 | bool operator==(const ValueIterator &that) const; 97 | 98 | /** 99 | * Compare with other iterator 100 | * @param that 101 | * @return bool 102 | */ 103 | bool operator!=(const ValueIterator &that) const; 104 | 105 | /** 106 | * Dereference, this returns a std::pair with the current key and value 107 | * @return std::pair 108 | */ 109 | const std::pair &operator*() const; 110 | 111 | /** 112 | * Dereference, this returns a std::pair with the current key and value 113 | * @return std::pair 114 | */ 115 | const std::pair *operator->() const; 116 | 117 | private: 118 | /** 119 | * Pointer to the actual implementation 120 | * @var std::unique_ptr 121 | */ 122 | std::unique_ptr _impl; 123 | 124 | }; 125 | 126 | /** 127 | * End namespace 128 | */ 129 | } 130 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Version.h 3 | * 4 | * Macro with API version. The API version number prevents that 5 | * extensions are loaded that are incompatible with the libphpcpp.so 6 | * library 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2015 Copernica BV 10 | */ 11 | 12 | /** 13 | * Macro with version number (this is incremented with every release) 14 | */ 15 | #define PHPCPP_API_VERSION 20150126 16 | -------------------------------------------------------------------------------- /include/visibility.h: -------------------------------------------------------------------------------- 1 | /** 2 | * visibility.h 3 | * 4 | * This file defines macros used to define whether a symbol 5 | * should be exported. It is only used for classes and 6 | * functions that are defined in the public API to reduce 7 | * the size of the symbol table, make linking and loading 8 | * of the PHP-CPP library faster and generate more 9 | * optimized code as a result. 10 | * 11 | * @copyright 2015 Copernica B.V. 12 | */ 13 | 14 | #if defined _WIN32 || defined __CYGWIN__ 15 | #ifdef BUILDING_PHPCPP 16 | #ifdef __GNUC__ 17 | #define PHPCPP_EXPORT __attribute__ ((dllexport)) 18 | #else 19 | #define PHPCPP_EXPORT __declspec(dllexport) // Note: actually gcc seems to also supports this syntax. 20 | #endif 21 | #else 22 | #ifdef __GNUC__ 23 | #define DLL_EXPORT __attribute__ ((dllimport)) 24 | #else 25 | #define DLL_EXPORT __declspec(dllimport) // Note: actually gcc seems to also supports this syntax. 26 | #endif 27 | #endif 28 | #else 29 | #define PHPCPP_EXPORT __attribute__ ((visibility ("default"))) 30 | #endif 31 | -------------------------------------------------------------------------------- /include/zval.h: -------------------------------------------------------------------------------- 1 | /** 2 | * zval.h 3 | * 4 | * A buffer to have a zval on the stack without 5 | * needing to do any heap allocations 6 | * 7 | * @copyright 2016 Copernica B.V. 8 | */ 9 | 10 | /** 11 | * Include guard 12 | */ 13 | #pragma once 14 | 15 | /** 16 | * Dependencies 17 | */ 18 | #include 19 | 20 | /** 21 | * Forward declarations 22 | */ 23 | struct _zval_struct; 24 | 25 | /** 26 | * Typedef for zval aligned storage 27 | */ 28 | using aligned_zval_struct = typename std::aligned_storage<16>::type; 29 | 30 | /** 31 | * Start namespace 32 | */ 33 | namespace Php 34 | { 35 | 36 | /** 37 | * The zend value wrapper 38 | */ 39 | class Zval 40 | { 41 | private: 42 | /** 43 | * The zval buffer 44 | * @var aligned_zval_struct 45 | */ 46 | aligned_zval_struct _buffer; 47 | 48 | public: 49 | /** 50 | * Cast to a zval 51 | * 52 | * @return zend value structure 53 | */ 54 | operator _zval_struct * () const & 55 | { 56 | // reinterpret the value as a zval 57 | return const_cast(reinterpret_cast(&_buffer)); 58 | } 59 | 60 | /** 61 | * Cast to a zval 62 | * 63 | * @return zend value structure 64 | */ 65 | struct _zval_struct &operator* () const & 66 | { 67 | // reinterpret and dereference 68 | return *const_cast(reinterpret_cast(&_buffer)); 69 | } 70 | 71 | /** 72 | * In case this is a reference, dereference it into a zval.. In case it isn't 73 | * the actual value is returned. 74 | * @return struct _zval_struct* 75 | */ 76 | struct _zval_struct *dereference() const; 77 | }; 78 | 79 | /** 80 | * End namespace 81 | */ 82 | } 83 | -------------------------------------------------------------------------------- /phpcpp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * phpcpp.h 3 | * 4 | * Library to build PHP extensions with CPP 5 | * 6 | * @copyright 2013 - 2019 Copernica BV 7 | * @author Emiel Bruijntjes 8 | */ 9 | 10 | #ifndef PHPCPP_H 11 | #define PHPCPP_H 12 | 13 | /** 14 | * Other C and C++ libraries that PhpCpp depends on 15 | */ 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | /** 28 | * Include all headers files that are related to this library 29 | */ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | 78 | #endif /* phpcpp.h */ 79 | -------------------------------------------------------------------------------- /zend/boolmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * BoolMember.h 3 | * 4 | * Implementation for a property that is initially set to a boolean value 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class BoolMember : public Member 19 | { 20 | private: 21 | /** 22 | * The value 23 | * @var bool 24 | */ 25 | bool _value; 26 | 27 | public: 28 | /** 29 | * Constructor 30 | * @param name 31 | * @param value 32 | * @param flags 33 | */ 34 | BoolMember(const char *name, bool value, int flags) : Member(name, flags), _value(value) {} 35 | 36 | /** 37 | * Destructor 38 | */ 39 | virtual ~BoolMember() {} 40 | 41 | /** 42 | * Virtual method to declare a class constant 43 | * @param entry Class entry 44 | */ 45 | virtual void constant(struct _zend_class_entry *entry) override 46 | { 47 | zend_declare_class_constant_bool(entry, _name.c_str(), _name.size(), _value); 48 | } 49 | 50 | /** 51 | * Virtual method to declare the property 52 | * @param entry Class entry 53 | */ 54 | virtual void declare(struct _zend_class_entry *entry) override 55 | { 56 | // char* cast is necessary for php 5.3 57 | zend_declare_property_bool(entry, (char *)_name.c_str(), _name.size(), _value, _flags); 58 | } 59 | }; 60 | 61 | /** 62 | * End of namespace 63 | */ 64 | } 65 | 66 | -------------------------------------------------------------------------------- /zend/classtype.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file classtype.h 3 | * 4 | * Internal class types enumeration. 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 - 2022 Copernica BV 8 | */ 9 | 10 | /** 11 | * Include guard 12 | */ 13 | #pragma once 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Enumeration definition. 22 | * This is different for different PHP versions 23 | */ 24 | enum class ClassType { 25 | Regular = 0x00, 26 | Interface = ZEND_ACC_INTERFACE, 27 | Abstract = ZEND_ACC_ABSTRACT, 28 | Final = ZEND_ACC_FINAL, 29 | }; 30 | 31 | /** 32 | * End namespace 33 | */ 34 | } 35 | -------------------------------------------------------------------------------- /zend/compileroptions.h: -------------------------------------------------------------------------------- 1 | /** 2 | * CompilerOptions.h 3 | * 4 | * Helper class to temporarily set compiler options 5 | * 6 | * When an object is destructed, it automatically restored the previous compiler settings 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | 12 | /** 13 | * Open PHP namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Class definition 19 | */ 20 | class CompilerOptions 21 | { 22 | private: 23 | /** 24 | * The original compiler options 25 | * @var uint32_t 26 | */ 27 | uint32_t _original; 28 | 29 | public: 30 | /** 31 | * Constructor 32 | * @param options 33 | */ 34 | CompilerOptions(uint32_t options) 35 | { 36 | // remember the old compiler options before we set temporary compile options 37 | _original = CG(compiler_options); 38 | 39 | // we're going to evaluate only once 40 | CG(compiler_options) = options; 41 | } 42 | 43 | /** 44 | * Destructor 45 | */ 46 | virtual ~CompilerOptions() 47 | { 48 | // restore original options 49 | CG(compiler_options) = _original; 50 | } 51 | }; 52 | 53 | /** 54 | * End of namespace 55 | */ 56 | } 57 | -------------------------------------------------------------------------------- /zend/constant.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Constant.cpp 3 | * 4 | * Implementation file for the constant class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2015 Copernica BV 8 | */ 9 | #include "includes.h" 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Constructor 18 | * @param name Constant name 19 | * @param value Constant value 20 | */ 21 | Constant::Constant(const char *name, std::nullptr_t value) : 22 | _impl(new ConstantImpl(name, value)) {} 23 | 24 | /** 25 | * Constructor 26 | * @param name Constant name 27 | * @param value Constant value 28 | */ 29 | Constant::Constant(const char *name, bool value) : 30 | _impl(new ConstantImpl(name, value)) {} 31 | 32 | /** 33 | * Constructor 34 | * @param name Constant name 35 | * @param value Constant value 36 | */ 37 | Constant::Constant(const char *name, int32_t value) : 38 | _impl(new ConstantImpl(name, value)) {} 39 | 40 | /** 41 | * Constructor 42 | * @param name Constant name 43 | * @param value Constant value 44 | */ 45 | Constant::Constant(const char *name, int64_t value) : 46 | _impl(new ConstantImpl(name, value)) {} 47 | 48 | /** 49 | * Constructor 50 | * @param name Constant name 51 | * @param value Constant value 52 | */ 53 | Constant::Constant(const char *name, double value) : 54 | _impl(new ConstantImpl(name, value)) {} 55 | 56 | /** 57 | * Constructor 58 | * @param name Constant name 59 | * @param value Constant value 60 | */ 61 | Constant::Constant(const char *name, const char *value) : 62 | _impl(new ConstantImpl(name, value)) {} 63 | 64 | /** 65 | * Constructor 66 | * @param name Constant name 67 | * @param value Constant value 68 | * @param size Value size 69 | */ 70 | Constant::Constant(const char *name, const char *value, size_t size) : 71 | _impl(new ConstantImpl(name, value, size)) {} 72 | 73 | /** 74 | * Constructor 75 | * @param name Constant name 76 | * @param value Constant value 77 | */ 78 | Constant::Constant(const char *name, const std::string &value) : 79 | _impl(new ConstantImpl(name, value)) {} 80 | 81 | /** 82 | * Add the constant to a class 83 | * 84 | * You normally do not have to call this method yourself. You can simply 85 | * do one of the following method calls to create class constants: 86 | * 87 | * myclass.property("MY_CONSTANT", "value", Php::Const); 88 | * myclass.constant("MY_CONSTANT", "value"); 89 | * myclass.add(Php::Constant("MY_CONSTANT", "value")); 90 | * 91 | * All of the calls have the same result, it is up to you to decide which 92 | * one suits you most. If you use the last one - using a Php::Constant 93 | * class - the PHP-CPP library will call this "addTo()" method internally 94 | * to forward the call to one of the other methods. 95 | * 96 | * @param clss Class to which the constant is added 97 | * @internal 98 | */ 99 | void Constant::addTo(ClassBase &clss) const 100 | { 101 | // pass on to the implementation 102 | _impl->addTo(clss); 103 | } 104 | 105 | /** 106 | * End of namespace 107 | */ 108 | } 109 | 110 | -------------------------------------------------------------------------------- /zend/delayedfree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DelayedFree.h 3 | * 4 | * Sometimes a piece of data must be freed when a function gets out of 5 | * scope. In stead of putting the efree() call right before every possible 6 | * function end point (exceptions, returns, zend_errors()), we can use 7 | * this simple class instead 8 | * 9 | * @author Emiel Bruijntjes 10 | * @copyright 2015 Copernica BV 11 | */ 12 | 13 | /** 14 | * Set up namespace 15 | */ 16 | namespace Php { 17 | 18 | /** 19 | * Class definition 20 | */ 21 | class DelayedFree 22 | { 23 | private: 24 | /** 25 | * The data that has to be free'd when the object falls out of scope 26 | * @var void* 27 | */ 28 | void *_data; 29 | 30 | public: 31 | /** 32 | * Constructor 33 | * @param data Data that will be freed on destruction 34 | */ 35 | DelayedFree(void *data) : _data(data) {} 36 | 37 | /** 38 | * Destructor 39 | */ 40 | virtual ~DelayedFree() 41 | { 42 | // free the data 43 | efree(_data); 44 | } 45 | }; 46 | 47 | /** 48 | * End of namespace 49 | */ 50 | } 51 | -------------------------------------------------------------------------------- /zend/error.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Error.cpp 3 | * 4 | * Implementation file for the Error class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2019 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Rethrow the exception / make sure that it ends up in PHP space 22 | */ 23 | void Error::rethrow() 24 | { 25 | // add the exception to userspace 26 | zend_throw_exception(zend_ce_error, what(), _code); 27 | } 28 | 29 | /** 30 | * End of namespace 31 | */ 32 | } 33 | 34 | -------------------------------------------------------------------------------- /zend/eval.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Eval.cpp 3 | * 4 | * This file holds the implementation for the Php::eval() function 5 | * 6 | * @author andot 7 | */ 8 | 9 | /** 10 | * Dependencies 11 | */ 12 | #include "includes.h" 13 | 14 | /** 15 | * Open PHP namespace 16 | */ 17 | namespace Php { 18 | 19 | /** 20 | * Evaluate a PHP string 21 | * @param phpCode The PHP code to evaluate 22 | * @return Value The result of the evaluation 23 | */ 24 | Value eval(const char *phpCode) 25 | { 26 | // we have a script for this 27 | return Script(phpCode).execute(); 28 | } 29 | 30 | /** 31 | * Include a file 32 | * @param filename 33 | * @return Value 34 | */ 35 | Value include(const char *filename) 36 | { 37 | // we can simply execute a file 38 | return File(filename).execute(); 39 | } 40 | 41 | /** 42 | * Include a file only once 43 | * @param filename 44 | * @return Value 45 | */ 46 | Value include_once(const char *filename) 47 | { 48 | // we can simply execute a file 49 | return File(filename).once(); 50 | } 51 | 52 | /** 53 | * Require a file 54 | * This causes a fatal error if the file does not exist 55 | * @param filename 56 | * @return Value 57 | */ 58 | Value require(const char *filename) 59 | { 60 | // create the file 61 | File file(filename); 62 | 63 | // execute if it exists 64 | if (file.exists()) return file.execute(); 65 | 66 | // trigger fatal error 67 | error << filename << " does not exist" << std::flush; 68 | 69 | // unreachable 70 | return nullptr; 71 | } 72 | 73 | /** 74 | * Require a file only once 75 | * This causes a fatal error if the file does not exist 76 | * @param filename 77 | * @return Value 78 | */ 79 | Value require_once(const char *filename) 80 | { 81 | // create the file 82 | File file(filename); 83 | 84 | // execute if it exists 85 | if (file.exists()) return file.once(); 86 | 87 | // trigger fatal error 88 | error << filename << " does not exist" << std::flush; 89 | 90 | // unreachable 91 | return nullptr; 92 | } 93 | 94 | /** 95 | * Implementation of the dl() function - activate a different PHP extension 96 | * 97 | * If you open an extension persistently, the static variables inside it are 98 | * kept open for as long as apache runs. 99 | * 100 | * @param filename 101 | * @param persistent 102 | */ 103 | bool dl(const char *filename, bool persistent) 104 | { 105 | // create the module 106 | Module module(filename, persistent); 107 | 108 | // start the module 109 | return module.start(); 110 | } 111 | 112 | /** 113 | * End of namespace 114 | */ 115 | } 116 | -------------------------------------------------------------------------------- /zend/exception.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Exception.cpp 3 | * 4 | * Implementation file for the Exception class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2019 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Rethrow the exception / make sure that it ends up in PHP space 22 | */ 23 | void Exception::rethrow() 24 | { 25 | // add the exception to userspace 26 | zend_throw_exception(zend_ce_exception, what(), _code); 27 | } 28 | 29 | /** 30 | * End of namespace 31 | */ 32 | } 33 | 34 | -------------------------------------------------------------------------------- /zend/exception_handler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Exception_handler.cpp 3 | * 4 | * Set the exception handler 5 | * 6 | * @author Toon Schoenmakers 7 | */ 8 | 9 | /** 10 | * Dependencies 11 | */ 12 | #include "includes.h" 13 | #include "string.h" 14 | 15 | /** 16 | * Open the PHP namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Set a std::function as a php exception handler 22 | */ 23 | Value set_exception_handler(const std::function &handler) 24 | { 25 | // create a functor which wraps our callback 26 | Function functor(handler); 27 | 28 | // initialize our output value 29 | Value output; 30 | 31 | // turn our user_exception_handler into a Value so we can return the original one later on 32 | if (!Z_ISNULL(EG(user_exception_handler))) output = &EG(user_exception_handler); 33 | 34 | // detach so we have the zval 35 | auto value = functor.detach(true); 36 | 37 | // copy our zval into the user_exception_handler 38 | ZVAL_COPY(value, &EG(user_exception_handler)); 39 | 40 | // return the original handler 41 | return output; 42 | } 43 | 44 | /** 45 | * Set a std::function as a php error handler 46 | */ 47 | Value set_error_handler(const std::function &handler, Message message) 48 | { 49 | // create the functor which wraps our callback 50 | Function functor(handler); 51 | 52 | // initialize our output value 53 | Value output; 54 | 55 | // turn our user_error_handler into a Value if we have one, just so we can return it later on 56 | if (!Z_ISNULL(EG(user_error_handler))) output = &EG(user_error_handler); 57 | 58 | // detach so we have the zval 59 | auto value = functor.detach(true); 60 | 61 | // copy our zval into the user_error_handler 62 | ZVAL_COPY_VALUE(&EG(user_error_handler), value); 63 | EG(user_error_handler_error_reporting) = (int) message; 64 | 65 | // return the original handler 66 | return output; 67 | } 68 | 69 | /** 70 | * Modify the error reporting level, will return the old error reporting level. 71 | */ 72 | Value error_reporting(Message message) 73 | { 74 | // store the old error reporting value 75 | Value output(EG(error_reporting)); 76 | 77 | // create a small temporary buffer 78 | char str[21]; 79 | 80 | // write the level into this buffer 81 | int size = sprintf(str, "%d", (int) message); 82 | 83 | // if we failed for some reason we bail out 84 | if (size < 0) return false; 85 | 86 | // the entry to change - static to avoid unnecessary extra allocations 87 | static String entry{ "error_reporting" }; 88 | 89 | // alter the ini on the fly 90 | zend_alter_ini_entry_chars(entry, str, size, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); 91 | 92 | // return the output 93 | return output; 94 | } 95 | 96 | /** 97 | * End of namespace 98 | */ 99 | } 100 | -------------------------------------------------------------------------------- /zend/execarguments.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ExecArguments.h 3 | * 4 | * Helper class that we use to turn an array of Value objects into an 5 | * array of zval parameters 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2024 Copernica BV 9 | */ 10 | 11 | /** 12 | * Include guard 13 | */ 14 | #pragma once 15 | 16 | /** 17 | * Begin of namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class ExecArguments 25 | { 26 | private: 27 | /** 28 | * Short-array-optimization (most exec calls do not have more than 10 parameters) 29 | * @var zval[] 30 | */ 31 | zval _preallocated[10]; 32 | 33 | /** 34 | * The actual arguments 35 | * @var zval[] 36 | */ 37 | zval *_argv; 38 | 39 | /** 40 | * The number of arguments 41 | * @var size_t 42 | */ 43 | size_t _argc; 44 | 45 | public: 46 | /** 47 | * Default constructor 48 | */ 49 | ExecArguments() : _argv(_preallocated), _argc(0) {} 50 | 51 | /** 52 | * Constructor 53 | * @param argc 54 | * @param argv 55 | */ 56 | ExecArguments(size_t argc, Value argv[]) : _argv(_preallocated), _argc(argc) 57 | { 58 | // if there are too many arguments, we allocate them right away 59 | if (_argc > 10) _argv = (zval *)malloc(sizeof(zval) * _argc); 60 | 61 | // convert Value objects to zval array with references 62 | for (size_t i = 0; i < argc; ++i) 63 | { 64 | // make sure the original variable is a reference so that our copy points to the same data 65 | // @todo not sure if this is needed, do we need to turn the parameters into references to allow for pass-by-reference parameters? 66 | //if (!Z_ISREF_P(argv[i]._val)) ZVAL_MAKE_REF(argv[i]._val); 67 | 68 | // copy the zval 69 | ZVAL_COPY(&_argv[i], argv[i]._val); 70 | } 71 | } 72 | 73 | /** 74 | * No copying (we could implement this later, but for now this is not needed) 75 | * @param that 76 | */ 77 | ExecArguments(const ExecArguments &that) = delete; 78 | 79 | /** 80 | * Destructor 81 | */ 82 | virtual ~ExecArguments() 83 | { 84 | // destruct all zval objects 85 | for (size_t i = 0; i < _argc; ++i) zval_ptr_dtor(&_argv[i]); 86 | 87 | // deallocate memory 88 | if (_argv != _preallocated) free(_argv); 89 | } 90 | 91 | /** 92 | * Convert to a argv[] 93 | * @return zval[] 94 | */ 95 | zval *argv() { return _argv; } 96 | int argc() { return _argc; } 97 | }; 98 | 99 | /** 100 | * End of namespace 101 | */ 102 | } 103 | -------------------------------------------------------------------------------- /zend/executestate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ExecuteState.h 3 | * 4 | * Class that keeps the current execution state (this is used when a different 5 | * script or file is eval'ed to store the execution state so that we can switch 6 | * back to the original state. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | 12 | /** 13 | * Set up namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Helper class to store and restore the current opcode state 19 | * 20 | * When we're going to execute a set of instructions, we need to store the 21 | * current state of the Zend engine. After the instructions have been processed, 22 | * we can switch back to the original instructions 23 | */ 24 | class ExecuteState 25 | { 26 | private: 27 | /** 28 | * All the original settings 29 | * @var mixed 30 | */ 31 | zend_op_array *_active_op_array; 32 | zval *_return_value; 33 | const zend_op *_opline; 34 | 35 | /** 36 | * The new value for 'no-extensions' 37 | * @var int 38 | */ 39 | int _no_extensions; 40 | 41 | public: 42 | /** 43 | * No trivial constructor 44 | */ 45 | ExecuteState() = delete; 46 | 47 | /** 48 | * Constructor 49 | * @param no_extensions 50 | */ 51 | ExecuteState(int no_extensions) 52 | { 53 | // store all the original stuff 54 | _active_op_array = CG(active_op_array); 55 | _return_value = EG(current_execute_data)->return_value; 56 | _opline = EG(current_execute_data)->opline; 57 | _no_extensions = no_extensions; 58 | } 59 | 60 | /** 61 | * Destructor 62 | */ 63 | virtual ~ExecuteState() 64 | { 65 | // restore all settings 66 | EG(no_extensions) = _no_extensions; 67 | EG(current_execute_data)->opline = _opline; 68 | CG(active_op_array) = _active_op_array; 69 | EG(current_execute_data)->return_value = _return_value; 70 | } 71 | }; 72 | 73 | /** 74 | * End of namespace 75 | */ 76 | } 77 | 78 | -------------------------------------------------------------------------------- /zend/exists.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Exists.cpp 3 | * 4 | * This file holds the implementation of all *_exists() functions, 5 | * like class_exists(), et cetera 6 | * 7 | * @author andot 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | #include "string.h" 15 | 16 | /** 17 | * Open the PHP namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Check whether a class with a certain name exists 23 | * @param classname 24 | * @param len 25 | * @param autoload 26 | * @return bool 27 | */ 28 | bool class_exists(const char *classname, size_t len, bool autoload) 29 | { 30 | // should we autoload the class? 31 | if (autoload) 32 | { 33 | // retrieve class entry 34 | auto *ce = zend_lookup_class(String{ classname, len }); 35 | 36 | // no auto-load 37 | if (!ce) return false; 38 | 39 | // the found "class" could also be an interface or trait, which we do no want 40 | return (ce->ce_flags & (ZEND_ACC_INTERFACE | (ZEND_ACC_TRAIT - ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) == 0; 41 | } 42 | else 43 | { 44 | // starting slashes can be ignored 45 | if (len > 0 && classname[0] == '\\') { classname++; len--; } 46 | 47 | // create the string wrapper 48 | String string{ classname, len }; 49 | 50 | // copy the name to lowercase, but ignore the starting slash (if there is one) 51 | zend_str_tolower(string.data(), string.size()); 52 | 53 | // see if there is a class with this name 54 | auto *val = zend_hash_find(EG(class_table), string); 55 | 56 | // check whether something was found 57 | if (val == nullptr) return false; 58 | 59 | // the "something" could also be an interface or trait, which we do no want 60 | return !(((Z_CE_P(val))->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) > ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); 61 | } 62 | } 63 | 64 | /** 65 | * End of namespace 66 | */ 67 | } 68 | -------------------------------------------------------------------------------- /zend/extensionpath.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ExtensionPath.h 3 | * 4 | * Simply utility class that turns a pathname for an extension into a full 5 | * pathname that also takes the global extension_dir setting into account. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2015 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Class definition 18 | */ 19 | class ExtensionPath 20 | { 21 | private: 22 | /** 23 | * The actual value 24 | * @var std::string 25 | */ 26 | std::string _path; 27 | 28 | public: 29 | /** 30 | * Constructor 31 | * @param path 32 | */ 33 | ExtensionPath(const char *path) 34 | { 35 | // was an absole path given? 36 | if (path[0] && path[0] == '/') 37 | { 38 | // for absolute pathnames no extension_dir has to be checked 39 | _path = path; 40 | } 41 | else 42 | { 43 | // start with the extension dir 44 | _path = PG(extension_dir); 45 | 46 | // append slash 47 | if (_path[_path.size()-1] != '/') _path.push_back('/'); 48 | 49 | // and append path passed to the constructor 50 | _path.append(path); 51 | } 52 | } 53 | 54 | /** 55 | * Destructor 56 | */ 57 | virtual ~ExtensionPath() {} 58 | 59 | /** 60 | * Cast to string 61 | * @return std::string 62 | */ 63 | operator const std::string & () const 64 | { 65 | return _path; 66 | } 67 | 68 | /** 69 | * Cast to const-char* 70 | * @return const char * 71 | */ 72 | operator const char * () const 73 | { 74 | return _path.c_str(); 75 | } 76 | }; 77 | 78 | /** 79 | * End of nmaespace 80 | */ 81 | } 82 | 83 | -------------------------------------------------------------------------------- /zend/floatmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * FloatMember.h 3 | * 4 | * Implementation for a property that is initially set to a boolean value 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013, 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class FloatMember : public Member 19 | { 20 | private: 21 | /** 22 | * The value 23 | * @var double 24 | */ 25 | double _value; 26 | 27 | public: 28 | /** 29 | * Constructor 30 | * @param name 31 | * @param value 32 | * @param flags 33 | */ 34 | FloatMember(const char *name, double value, int flags) : Member(name, flags), _value(value) {} 35 | 36 | /** 37 | * Destructor 38 | */ 39 | virtual ~FloatMember() {} 40 | 41 | /** 42 | * Virtual method to declare class constant 43 | * @param entry Class entry 44 | */ 45 | virtual void constant(struct _zend_class_entry *entry) override 46 | { 47 | zend_declare_class_constant_double(entry, _name.c_str(), _name.size(), _value); 48 | } 49 | 50 | /** 51 | * Virtual method to declare the property 52 | * @param entry Class entry' 53 | */ 54 | virtual void declare(struct _zend_class_entry *entry) override 55 | { 56 | // converstion to char* necessary for php 5.3 57 | zend_declare_property_double(entry, (char *)_name.c_str(), _name.size(), _value, _flags); 58 | } 59 | }; 60 | 61 | /** 62 | * End of namespace 63 | */ 64 | } 65 | 66 | -------------------------------------------------------------------------------- /zend/function.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Function.cpp 3 | * 4 | * Implementation file for the Function class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2015 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Constructor 22 | * @param function The function to be wrapped 23 | */ 24 | Function::Function(const std::function &function) : Value(Object(Functor::entry(), new Functor(function))) {} 25 | 26 | /** 27 | * End of namespace 28 | */ 29 | } 30 | 31 | -------------------------------------------------------------------------------- /zend/functor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Functor.cpp 3 | * 4 | * Implementation file for the functor class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2015 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * The classentry 22 | * @var zend_class_entry 23 | */ 24 | zend_class_entry *Functor::_entry = nullptr; 25 | 26 | /** 27 | * Initialize the class 28 | */ 29 | void Functor::initialize() 30 | { 31 | // leap out if the class entry is already set 32 | if (_entry) return; 33 | 34 | // construct functor object 35 | static std::unique_ptr functor(new Class("PhpCpp::Functor")); 36 | 37 | // initialize the functor class 38 | _entry = functor->implementation()->initialize(functor.get(), ""); 39 | } 40 | 41 | /** 42 | * Shutdown the class 43 | */ 44 | void Functor::shutdown() 45 | { 46 | // we forget the entry 47 | _entry = nullptr; 48 | } 49 | 50 | /** 51 | * End of namespace 52 | */ 53 | } 54 | 55 | -------------------------------------------------------------------------------- /zend/functor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Functor.h 3 | * 4 | * We want to be able to wrap a std::function in an object and pass 5 | * that to PHP. The normal "Closure" class from the Zend engine 6 | * would be very suitable for that. However, the Zend engine does 7 | * not really allow us to add a secret pointer to such closure object. 8 | * 9 | * Therefore, we create our own Closure class, this time using PHP-CPP 10 | * code, to wrap a std::function. 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2015 Copernica BV 14 | */ 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class Functor : public Base 25 | { 26 | public: 27 | /** 28 | * Constructor 29 | * @param function The function to wrap 30 | */ 31 | Functor(const std::function &function) : _function(function) {} 32 | 33 | /** 34 | * Destructor 35 | */ 36 | virtual ~Functor() {} 37 | 38 | /** 39 | * Invoke the functor 40 | * @param params 41 | * @return Value 42 | */ 43 | Value __invoke(Parameters ¶ms) const 44 | { 45 | // pass on to the function 46 | return _function(params); 47 | } 48 | 49 | /** 50 | * Get the functor class entry 51 | * @return zend_class_entry 52 | */ 53 | static zend_class_entry *entry() 54 | { 55 | // get the "member" 56 | return _entry; 57 | } 58 | 59 | /** 60 | * Initialize the class 61 | */ 62 | static void initialize(); 63 | 64 | /** 65 | * Shutdown the class 66 | */ 67 | static void shutdown(); 68 | 69 | private: 70 | /** 71 | * The std::function that is wrapped in PHP code 72 | * @var std::function 73 | */ 74 | const std::function _function; 75 | 76 | /** 77 | * The classentry 78 | * @var zend_class_entry 79 | */ 80 | static zend_class_entry *_entry; 81 | 82 | }; 83 | 84 | /** 85 | * End of namespace 86 | */ 87 | } 88 | 89 | -------------------------------------------------------------------------------- /zend/global.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Global.cpp 3 | * 4 | * Implementation for the global variable 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | #include "includes.h" 10 | 11 | /** 12 | * Namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Move constructor 18 | * @param global 19 | */ 20 | Global::Global(Global &&global) _NOEXCEPT : 21 | Value(std::move(global)), 22 | _name(global._name), 23 | _exists(global._exists) 24 | { 25 | // remove from other global to avoid double free 26 | global._name = nullptr; 27 | } 28 | 29 | /** 30 | * Constructor for non-existing var 31 | * 32 | * @param name Name for the variable that does not exist 33 | */ 34 | Global::Global(const char *name) : 35 | Value(), 36 | _name(zend_string_init(name, ::strlen(name), 1)), 37 | _exists(false) {} 38 | 39 | /** 40 | * Alternative constructor for non-existing var 41 | * @param name 42 | */ 43 | Global::Global(const std::string &name) : 44 | Value(), 45 | _name(zend_string_init(name.data(), name.size(), 1)), 46 | _exists(false) {} 47 | 48 | /** 49 | * Constructor to wrap zval for existing global bar 50 | * @param name 51 | * @param val 52 | */ 53 | Global::Global(const char *name, struct _zval_struct *val) : 54 | Value(val, true), 55 | _name(zend_string_init(name, ::strlen(name), 1)), 56 | _exists(true) {} 57 | 58 | /** 59 | * Alternative constructor to wrap zval 60 | * @param name 61 | * @param val 62 | */ 63 | Global::Global(const std::string &name, struct _zval_struct *val) : 64 | Value(val, true), 65 | _name(zend_string_init(name.data(), name.size(), 1)), 66 | _exists(true) {} 67 | 68 | /** 69 | * Destructor 70 | */ 71 | Global::~Global() 72 | { 73 | // release the string 74 | if (_name) zend_string_release(_name); 75 | } 76 | 77 | /** 78 | * Function that is called when the value is updated 79 | * @return Value 80 | */ 81 | Global &Global::update() 82 | { 83 | // skip if the variable already exists 84 | if (_exists) return *this; 85 | 86 | // add one extra reference because the variable now is a global var too 87 | Z_TRY_ADDREF_P(_val); 88 | 89 | // add the variable to the globals 90 | zend_symtable_update_ind(&EG(symbol_table), _name, _val); 91 | 92 | // remember that the variable now exists 93 | _exists = true; 94 | 95 | // done 96 | return *this; 97 | } 98 | 99 | /** 100 | * End of namespace 101 | */ 102 | } 103 | 104 | -------------------------------------------------------------------------------- /zend/globals.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Globals.cpp 3 | * 4 | * Implementation of the globals class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | #include "includes.h" 10 | #include "string.h" 11 | 12 | /** 13 | * Namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Get access to the globals single instance 19 | * @return Globals 20 | */ 21 | Globals &Globals::instance() 22 | { 23 | static Globals globals; 24 | return globals; 25 | } 26 | 27 | /** 28 | * The one and only instance 29 | * @var Globals 30 | */ 31 | Globals &GLOBALS = Globals::instance(); 32 | 33 | /** 34 | * Get access to a global variable 35 | * @param name 36 | * @return Global 37 | */ 38 | Global Globals::operator[](const char *name) 39 | { 40 | // retrieve the variable (if it exists) 41 | zval *varvalue = zend_hash_find_ind(&EG(symbol_table), String{ name }); 42 | 43 | // check if the variable already exists 44 | if (!varvalue) 45 | { 46 | // the variable does not already exist, return a global object 47 | // that will automatically set the value when it is updated 48 | return Global(name); 49 | } 50 | else 51 | { 52 | // we are in the happy situation that the variable exists, we turn 53 | // this value into a reference value, and return that 54 | return Global(name, varvalue); 55 | } 56 | } 57 | 58 | /** 59 | * Get access to a global variable 60 | * @param name 61 | * @return Global 62 | */ 63 | Global Globals::operator[](const std::string &name) 64 | { 65 | // retrieve the variable (if it exists) 66 | auto *varvalue = zend_hash_find_ind(&EG(symbol_table), String{ name.data(), name.size() }); 67 | 68 | // check if the variable already exists 69 | if (!varvalue) 70 | { 71 | // the variable does not already exist, return a global object 72 | // that will automatically set the value when it is updated 73 | return Global(name); 74 | } 75 | else 76 | { 77 | // we are in the happy situation that the variable exists, we turn 78 | // this value into a reference value, and return that 79 | return Global(name, varvalue); 80 | } 81 | } 82 | 83 | /** 84 | * End of namespace 85 | */ 86 | } 87 | 88 | -------------------------------------------------------------------------------- /zend/hashmember.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * HashMember.cpp 3 | * 4 | * @author Emiel Bruijntjes 5 | * @copyright 2013 Copernica BV 6 | */ 7 | #include "includes.h" 8 | 9 | /** 10 | * Set up namespace 11 | */ 12 | namespace Php { 13 | 14 | /** 15 | * Custom output stream operator 16 | * @param stream 17 | * @param value 18 | * @return ostream 19 | */ 20 | std::ostream &operator<<(std::ostream &stream, const HashMember &value) 21 | { 22 | return stream << value.value(); 23 | } 24 | 25 | /** 26 | * Custom output stream operator 27 | * @param stream 28 | * @param value 29 | * @return ostream 30 | */ 31 | std::ostream &operator<<(std::ostream &stream, const HashMember &value) 32 | { 33 | return stream << value.value(); 34 | } 35 | 36 | /** 37 | * End of namespace 38 | */ 39 | } 40 | 41 | -------------------------------------------------------------------------------- /zend/ini.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Ini.cpp 3 | * 4 | * Implementation for .... 5 | * 6 | * @copyright 2013 Copernica BV 7 | */ 8 | #include "includes.h" 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Filling ini_entries 17 | * @param zend_ini_entry *ini_entry, int module_number 18 | * @param int module_number 19 | */ 20 | void Ini::fill(zend_ini_entry_def *ini_entry, int module_number) 21 | { 22 | ini_entry->modifiable = static_cast(_place); 23 | ini_entry->name = _name.data(); 24 | ini_entry->name_length = _name.size(); 25 | ini_entry->on_modify = OnUpdateString; 26 | ini_entry->mh_arg1 = nullptr; 27 | #ifdef ZTS 28 | ini_entry->mh_arg2 = (void *) &phpcpp_globals_id; 29 | #else 30 | ini_entry->mh_arg2 = (void *) &phpcpp_globals; 31 | #endif 32 | ini_entry->mh_arg3 = nullptr; 33 | ini_entry->value = _value.data(); 34 | ini_entry->value_length = _value.size(); 35 | ini_entry->displayer = nullptr; 36 | } 37 | 38 | 39 | /** 40 | * End of namespace 41 | */ 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /zend/init.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Init.h 3 | * 4 | * Variables and structured required by the Zend engine to work 5 | * with global variables 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 Copernica BV 9 | */ 10 | 11 | /** 12 | * Namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * The way how PHP C API deals with "global" variables is peculiar. 18 | * 19 | * The following macros are supposed to turn into a structure that is going 20 | * to be instantiated for each parallel running request, and for which the 21 | * PHP engine allocates a certain amount of memory, and a magic pointer that 22 | * is passed and should be forwarded to every thinkable PHP function. 23 | * 24 | * We don't use this architecture. We have our own environment object 25 | * that makes much more sense, and that we use. However, the Zend engine 26 | * expects this structure and this structure to exist. 27 | */ 28 | ZEND_BEGIN_MODULE_GLOBALS(phpcpp) 29 | ZEND_END_MODULE_GLOBALS(phpcpp) 30 | 31 | /** 32 | * And now we're going to define a macro. This also is a uncommon architecture 33 | * from PHP to get access to a variable from the structure above. 34 | */ 35 | #ifdef ZTS 36 | #define PHPCPP_G(v) TSRMG(phpcpp_globals_id, phpcpp_globals *, v) 37 | #else 38 | #define PHPCPP_G(v) (phpcpp_globals.v) 39 | #endif 40 | 41 | /** 42 | * We're almost there, we now need to declare an instance of the 43 | * structure defined above (if building for a single thread) or some 44 | * sort of impossible to understand magic pointer-to-a-pointer (for 45 | * multi-threading builds). We make this a static variable because 46 | * this already is bad enough. 47 | */ 48 | extern ZEND_DECLARE_MODULE_GLOBALS(phpcpp) 49 | 50 | /** 51 | * End of namespace 52 | */ 53 | } 54 | 55 | -------------------------------------------------------------------------------- /zend/inivalue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * IniValue.cpp 3 | * 4 | * Class IniValue designed for extracting values from ini entries 5 | * 6 | * @copyright 2013 Copernica BV 7 | */ 8 | #include "includes.h" 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Cast to a number 17 | * @return uint64_t 18 | */ 19 | int64_t IniValue::numericValue() const 20 | { 21 | return zend_ini_long(const_cast(_name.c_str()), _name.size(), _isorig); 22 | 23 | } 24 | 25 | /** 26 | * Get access to the raw buffer for read operationrs. 27 | * @return const char * 28 | */ 29 | const char* IniValue::rawValue() const 30 | { 31 | return zend_ini_string(const_cast(_name.c_str()), _name.size(), _isorig); 32 | } 33 | 34 | /** 35 | * Cast to a floating point 36 | * @return double 37 | */ 38 | IniValue::operator double() const 39 | { 40 | return zend_ini_double(const_cast(_name.c_str()), _name.size(), _isorig); 41 | } 42 | 43 | /** 44 | * Custom output stream operator 45 | * @param stream 46 | * @param ini_val 47 | * @return ostream 48 | */ 49 | std::ostream &operator<<(std::ostream &stream, const IniValue &ini_val) 50 | { 51 | return stream << static_cast(ini_val); 52 | } 53 | 54 | /** 55 | * End of namespace 56 | */ 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /zend/interface.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface.cpp 3 | * 4 | * Implementation file for the Interface class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2022 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Constructor 22 | * @param name 23 | */ 24 | Interface::Interface(const char *name) : ClassBase(name, ClassType::Interface) {} 25 | 26 | /** 27 | * End of namespace 28 | */ 29 | } 30 | 31 | -------------------------------------------------------------------------------- /zend/invaliditerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * InvalidIterator.h 3 | * 4 | * Iterator class that is used for value objects that are not even 5 | * iteratable. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2014 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Class definition 18 | */ 19 | class InvalidIterator : public ValueIteratorImpl 20 | { 21 | public: 22 | /** 23 | * Clone the object 24 | * @return ValueIteratorImpl 25 | */ 26 | virtual ValueIteratorImpl *clone() 27 | { 28 | // create a new instance 29 | return new InvalidIterator(*this); 30 | } 31 | 32 | /** 33 | * Increment position (pre-increment) 34 | * @return bool 35 | */ 36 | virtual bool increment() override 37 | { 38 | return false; 39 | } 40 | 41 | /** 42 | * Decrement position (pre-decrement) 43 | * @return bool 44 | */ 45 | virtual bool decrement() override 46 | { 47 | return false; 48 | } 49 | 50 | /** 51 | * Compare with other iterator 52 | * @param that 53 | * @return bool 54 | */ 55 | virtual bool equals(const ValueIteratorImpl *that) const override 56 | { 57 | // the other iterator is also an invalid-iterator, and all invalid 58 | // iterators are equal 59 | return true; 60 | } 61 | 62 | /** 63 | * Derefecence, this returns a std::pair with the current key and value 64 | * @return std::pair 65 | */ 66 | virtual const std::pair ¤t() const override 67 | { 68 | // this method is never called, when it is, we create a static instance 69 | static std::pair result; 70 | 71 | // return it 72 | return result; 73 | } 74 | }; 75 | 76 | /** 77 | * End namespace 78 | */ 79 | } 80 | 81 | -------------------------------------------------------------------------------- /zend/lowercase.h: -------------------------------------------------------------------------------- 1 | /** 2 | * LowerCase.h 3 | * 4 | * Class to temporary convert a name to lowercase 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2016 Copernica BV 8 | */ 9 | 10 | /** 11 | * Include guard 12 | */ 13 | #pragma once 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Class definition 22 | */ 23 | class LowerCase 24 | { 25 | private: 26 | /** 27 | * The lowercase name 28 | * @var zend_string 29 | */ 30 | zend_string *_name; 31 | 32 | public: 33 | /** 34 | * Constructor 35 | * @param name the original name 36 | */ 37 | LowerCase(zend_string *name) : 38 | _name(zend_string_tolower(name)) {} 39 | 40 | /** 41 | * No copy'ing or moving 42 | * @param that 43 | */ 44 | LowerCase(const LowerCase &that) = delete; 45 | LowerCase(LowerCase &&that) = delete; 46 | 47 | /** 48 | * Destructor 49 | */ 50 | virtual ~LowerCase() 51 | { 52 | // release the data 53 | zend_string_release(_name); 54 | } 55 | 56 | /** 57 | * Expose internal value 58 | * @return zend_string* 59 | */ 60 | zend_string *value() 61 | { 62 | // expose member 63 | return _name; 64 | } 65 | 66 | /** 67 | * Cast to a zend_string 68 | * @return zend_string* 69 | */ 70 | operator zend_string* () 71 | { 72 | // expose member 73 | return _name; 74 | } 75 | }; 76 | 77 | /** 78 | * End of namespace 79 | */ 80 | } 81 | -------------------------------------------------------------------------------- /zend/macros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Macros.h 3 | * 4 | * Some macros have changed or have been removed between PHP versions. 5 | * In this file we write custom versions of such macros to overcome that 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2023 Copernica BV 9 | */ 10 | 11 | /** 12 | * Include guard 13 | */ 14 | #pragma once 15 | 16 | /** 17 | * The "SEPARATE_ZVAL_IF_NOT_REF()" macro has been removed 18 | */ 19 | #ifndef SEPARATE_ZVAL_IF_NOT_REF 20 | #define SEPARATE_ZVAL_IF_NOT_REF(zv) do { \ 21 | zval *_zv = (zv); \ 22 | if (Z_TYPE_P(_zv) == IS_ARRAY) { \ 23 | SEPARATE_ARRAY(_zv); \ 24 | } \ 25 | } while(0) 26 | #endif 27 | -------------------------------------------------------------------------------- /zend/member.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Member.h 3 | * 4 | * Base class for properties of a class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013, 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class Member 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the member 24 | * @param flags Flag access to a class member (public, protected etc) 25 | */ 26 | Member(const char *name, int flags) : _name(name), _flags(flags) {} 27 | 28 | /** 29 | * Destructor 30 | */ 31 | virtual ~Member() {} 32 | 33 | /** 34 | * Initialize the member 35 | * @param zend_class_entry 36 | */ 37 | void initialize(struct _zend_class_entry *entry) 38 | { 39 | if (_flags == Const) constant(entry); 40 | else declare(entry); 41 | } 42 | 43 | protected: 44 | /** 45 | * Internal method to declare the property as constant 46 | * @param zend_class_entry 47 | */ 48 | virtual void constant(struct _zend_class_entry *entry) = 0; 49 | 50 | /** 51 | * Internal method to declare the property 52 | * @param zend_class_entry 53 | */ 54 | virtual void declare(struct _zend_class_entry *entry) = 0; 55 | 56 | protected: 57 | /** 58 | * The member name 59 | * @var std::string 60 | */ 61 | std::string _name; 62 | 63 | /** 64 | * The member flags 65 | * @var int 66 | */ 67 | int _flags; 68 | }; 69 | 70 | /** 71 | * End of namespace 72 | */ 73 | } 74 | 75 | -------------------------------------------------------------------------------- /zend/members.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Members.cpp 3 | * 4 | * Implementation of the members class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | #include "includes.h" 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | ///** 17 | // * Destructor 18 | // */ 19 | //Members::~Members() 20 | //{ 21 | // // check if there are methods 22 | // if (_methods) delete[] _methods; 23 | //} 24 | // 25 | ///** 26 | // * Number of methods 27 | // * @return integer 28 | // */ 29 | //int Members::methods() 30 | //{ 31 | // // result variable 32 | // int result = 0; 33 | // 34 | // // loop through the functions 35 | // for (auto it = begin(); it != end(); it++) 36 | // { 37 | // // check if this is a method 38 | // if (it->isMethod()) result++; 39 | // } 40 | // 41 | // // done 42 | // return result; 43 | //} 44 | // 45 | ///** 46 | // * Get access to the methods 47 | // * @return Methods 48 | // */ 49 | //struct _zend_function_entry *Members::methods(const char *classname) 50 | //{ 51 | // // already set? 52 | // if (_methods) return _methods; 53 | // 54 | // // the number of methods 55 | // int count = methods(); 56 | // 57 | // // allocate memory for the functions 58 | // _methods = new zend_function_entry[count + 1]; 59 | // 60 | // // keep iterator counter 61 | // int i = 0; 62 | // 63 | // // loop through the functions 64 | // for (auto it = begin(); it != end(); it++) 65 | // { 66 | // // skip if this is not a method 67 | // if (!it->isMethod()) continue; 68 | // 69 | // // retrieve entry 70 | // zend_function_entry *entry = &_methods[i++]; 71 | // 72 | // // let the function fill the entry 73 | // it->initialize(classname, entry); 74 | // } 75 | // 76 | // // last entry should be set to all zeros 77 | // zend_function_entry *last = &_methods[i]; 78 | // 79 | // // all should be set to zero 80 | // memset(last, 0, sizeof(zend_function_entry)); 81 | // 82 | // // done 83 | // return _methods; 84 | //} 85 | // 86 | /** 87 | * End of namespace 88 | */ 89 | } 90 | 91 | -------------------------------------------------------------------------------- /zend/module.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Module.cpp 3 | * 4 | * Module implementation file 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2015 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * The persistent handles 22 | * @var Module::Persistent 23 | */ 24 | Module::Persistent Module::_persistent; 25 | 26 | /** 27 | * End of namespace 28 | */ 29 | } 30 | 31 | -------------------------------------------------------------------------------- /zend/notimplemented.h: -------------------------------------------------------------------------------- 1 | /** 2 | * NotImplemented.h 3 | * 4 | * Exception that is thrown and catched by the library internally to detect 5 | * if a magic method was implemented or not. 6 | * 7 | * Classes have magic methods (like __unset, __isset, etcetera). These methods 8 | * can be implemented by the extension writer, but they do not have to be. 9 | * 10 | * The default implementation of the methods _could_ be to pass on the method 11 | * to the original Zend engine, but the problem is that the magic methods from 12 | * the PHP-CPP library do not have the same signature as the functions in the 13 | * Zend engine. Passing them on directly is thus not possible. 14 | * 15 | * For that reason, the default implementation throw an exception that is 16 | * immediately caught by the PHP-CPP library, so that it knows that the user 17 | * has not overridden the methods, and the default Zend engine magic method 18 | * can be called instead 19 | * 20 | * @author Emiel Bruijntjes 21 | * @copyright 2014 Copernica BV 22 | */ 23 | 24 | /** 25 | * Set up namespace 26 | */ 27 | namespace Php { 28 | 29 | /** 30 | * Class definition 31 | */ 32 | class NotImplemented : public std::exception 33 | { 34 | public: 35 | /** 36 | * Constructor 37 | */ 38 | NotImplemented() : std::exception() {} 39 | 40 | /** 41 | * Destructor 42 | */ 43 | virtual ~NotImplemented() throw() {} 44 | 45 | }; 46 | 47 | /** 48 | * End namespace 49 | */ 50 | } 51 | 52 | -------------------------------------------------------------------------------- /zend/nullmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * NullMember.h 3 | * 4 | * Implementation for a property that is initially set to NULL 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class NullMember : public Member 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name 24 | * @param flags 25 | */ 26 | NullMember(const char *name, int flags) : Member(name, flags) {} 27 | 28 | /** 29 | * Destructor 30 | */ 31 | virtual ~NullMember() {} 32 | 33 | /** 34 | * Internal method to declare the property as constant 35 | * @param zend_class_entry 36 | */ 37 | virtual void constant(struct _zend_class_entry *entry) override 38 | { 39 | zend_declare_class_constant_null(entry, _name.c_str(), _name.size()); 40 | } 41 | 42 | /** 43 | * Virtual method to declare the property 44 | * @param entry Class entry 45 | */ 46 | virtual void declare(struct _zend_class_entry *entry) override 47 | { 48 | zend_declare_property_null(entry, _name.c_str(), _name.size(), _flags); 49 | } 50 | }; 51 | 52 | /** 53 | * End of namespace 54 | */ 55 | } 56 | 57 | -------------------------------------------------------------------------------- /zend/numericmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * NumericMember.h 3 | * 4 | * Implementation for a property that is initially set to a numeric value 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013, 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class NumericMember : public Member 19 | { 20 | private: 21 | /** 22 | * The value 23 | * @var long 24 | */ 25 | long _value; 26 | 27 | public: 28 | /** 29 | * Constructor 30 | * @param name 31 | * @param value 32 | * @param flags 33 | */ 34 | NumericMember(const char *name, long value, int flags) : Member(name, flags), _value(value) {} 35 | 36 | /** 37 | * Destructor 38 | */ 39 | virtual ~NumericMember() {} 40 | 41 | /** 42 | * Declare class constant 43 | * @param entry Class entry 44 | */ 45 | virtual void constant(struct _zend_class_entry *entry) override 46 | { 47 | zend_declare_class_constant_long(entry, _name.c_str(), _name.size(), _value); 48 | } 49 | 50 | /** 51 | * Virtual method to declare the property 52 | * @param entry Class entry 53 | */ 54 | virtual void declare(struct _zend_class_entry *entry) override 55 | { 56 | zend_declare_property_long(entry, _name.c_str(), _name.size(), _value, _flags); 57 | } 58 | }; 59 | 60 | /** 61 | * End of namespace 62 | */ 63 | } 64 | 65 | -------------------------------------------------------------------------------- /zend/opcodes.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Opcodes.h 3 | * 4 | * Class represents a set of opcodes of a PHP script that can be executed. This 5 | * is an internal file that you normally do not have to instantiate yourself. 6 | * Better use the Php::Script of Php::File classes. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 - 2019 Copernica BV 10 | */ 11 | 12 | /** 13 | * Forward declarations 14 | */ 15 | struct _zend_op_array; 16 | 17 | /** 18 | * Namespace 19 | */ 20 | namespace Php { 21 | 22 | /** 23 | * Class definition 24 | */ 25 | class Opcodes 26 | { 27 | public: 28 | /** 29 | * Constructor 30 | * @param opcodes 31 | */ 32 | Opcodes(struct _zend_op_array *opcodes) : _opcodes(opcodes) 33 | { 34 | } 35 | 36 | /** 37 | * Destructor 38 | */ 39 | virtual ~Opcodes() 40 | { 41 | // leap out if opcodes were not valid 42 | if (!_opcodes) return; 43 | 44 | // clean up opcodes 45 | destroy_op_array(_opcodes); 46 | efree(_opcodes); 47 | } 48 | 49 | /** 50 | * Are the opcodes valid? 51 | * @return bool 52 | */ 53 | bool valid() const 54 | { 55 | return _opcodes != nullptr; 56 | } 57 | 58 | /** 59 | * Execute the opcodes 60 | * @return Value 61 | */ 62 | Value execute() const 63 | { 64 | // if the script could not be compiled, we return null 65 | if (!_opcodes) return nullptr; 66 | 67 | // pointer that is going to hold the return value of the script 68 | zval retval; 69 | 70 | // initialize to null 71 | ZVAL_NULL(&retval); 72 | 73 | // the zend engine is probably already busy processing opcodes, so we store 74 | // the current execute state before we're going to switch the runtime to 75 | // our own set of opcodes 76 | ExecuteState execState(0); 77 | 78 | // old execute state has been saved (and will automatically be restored when 79 | // the oldstate is destructed), so we can now safely overwrite all the settings 80 | CG(active_op_array) = _opcodes; 81 | EG(no_extensions) = 1; 82 | if (!EG(current_execute_data)->symbol_table) zend_rebuild_symbol_table(); 83 | 84 | // the current exception state 85 | State state; 86 | 87 | // execute the code 88 | zend_execute(_opcodes, &retval); 89 | 90 | // was an exception thrown inside the eval()'ed code? In that case we 91 | // throw a C++ new exception to give the C++ code the chance to catch it 92 | state.rethrow(); 93 | 94 | // we're ready if there is no return value 95 | if (ZVAL_IS_NULL(&retval)) return nullptr; 96 | 97 | // wrap the return value 98 | Value result(&retval); 99 | 100 | // copy the pointer into a value object, and return that 101 | return result; 102 | } 103 | 104 | private: 105 | /** 106 | * The opcodes 107 | * @var zend_op_array 108 | */ 109 | struct _zend_op_array *_opcodes; 110 | }; 111 | 112 | /** 113 | * End of namespace 114 | */ 115 | } 116 | 117 | -------------------------------------------------------------------------------- /zend/parametersimpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ParametersImpl.h 3 | * 4 | * Extended parameters class that can be instantiated 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class ParametersImpl : public Parameters 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param this_ptr Pointer to the object 24 | * @param argc Number of arguments 25 | */ 26 | ParametersImpl(zval *this_ptr, uint32_t argc) : Parameters(this_ptr ? ObjectImpl::find(this_ptr)->object() : nullptr) 27 | { 28 | // reserve plenty of space 29 | reserve(argc); 30 | 31 | // array to store all the arguments in 32 | zval* arguments = static_cast(alloca(argc * sizeof(zval))); 33 | 34 | // retrieve the arguments 35 | zend_get_parameters_array_ex(argc, arguments); 36 | 37 | // loop through the arguments 38 | for (uint32_t i=0; i 7 | */ 8 | 9 | /** 10 | * Dependencies 11 | */ 12 | #include "includes.h" 13 | 14 | /** 15 | * Open PHP namespace 16 | */ 17 | namespace Php { 18 | 19 | /** 20 | * Retrieve the sapi name we're running on 21 | * @return const char* 22 | */ 23 | const char *sapi_name() 24 | { 25 | return sapi_module.name; 26 | } 27 | 28 | /** 29 | * End of namespace 30 | */ 31 | } 32 | -------------------------------------------------------------------------------- /zend/script.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Script.cpp 3 | * 4 | * Implementation file for the script class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Open PHP namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Helper function to compile the source code 22 | * @param name name of the script 23 | * @param script actual PHP code 24 | * @param size length of the string 25 | * @return opcodes 26 | */ 27 | zend_op_array *Script::compile(const char *name, const char *phpcode, size_t size) 28 | { 29 | // Sadly, there is not a simple Zend function to compile a string into opcodes, 30 | // so we basically copy the code that we found in zend_execute_API.c inside 31 | // the zend_eval_stringl() function into this file here. However, the code 32 | // found there is full of zval manipulation, for which we can use the much 33 | // simpler Php::Value object 34 | Php::Value source(phpcode, size); 35 | 36 | // remember the old compiler options, and set new compiler options 37 | CompilerOptions options(ZEND_COMPILE_DEFAULT_FOR_EVAL); 38 | 39 | // compile the string 40 | #if PHP_VERSION_ID < 80000 41 | return zend_compile_string(source._val, (char *)name); 42 | #elif PHP_VERSION_ID < 80200 43 | return zend_compile_string(zval_get_string(source._val), (char*)name); 44 | #else 45 | return zend_compile_string(zval_get_string(source._val), (char*)name, ZEND_COMPILE_POSITION_AT_OPEN_TAG); 46 | #endif 47 | } 48 | 49 | /** 50 | * Constructor 51 | * @param name name of the script 52 | * @param script actual PHP code 53 | * @param size length of the string 54 | */ 55 | Script::Script(const char *name, const char *phpcode, size_t size) _NOEXCEPT 56 | { 57 | // construct opcodes 58 | _opcodes = new Opcodes(compile(name, phpcode, size)); 59 | } 60 | 61 | /** 62 | * Destructor 63 | */ 64 | Script::~Script() 65 | { 66 | // remove opcodes 67 | delete _opcodes; 68 | } 69 | 70 | /** 71 | * Is the script a valid PHP script without syntax errors? 72 | * @return bool 73 | */ 74 | bool Script::valid() const 75 | { 76 | // check opcodes 77 | return _opcodes && _opcodes->valid(); 78 | } 79 | 80 | /** 81 | * Execute the script 82 | * The return value of the script is returned 83 | * @return Value 84 | */ 85 | Value Script::execute() const 86 | { 87 | // pass on to opcodes 88 | if (!_opcodes) return nullptr; 89 | 90 | // execute opcodes 91 | return _opcodes->execute(); 92 | } 93 | 94 | /** 95 | * End of namespace 96 | */ 97 | } 98 | 99 | -------------------------------------------------------------------------------- /zend/state.h: -------------------------------------------------------------------------------- 1 | /** 2 | * State.h 3 | * 4 | * Class that is used to store the state of current callstack and 5 | * whether an exception is now active. We use this before we make 6 | * a call to PHP userspace to see if the state has changed afterwards, 7 | * which means that an exception has bubbled up that should be handled 8 | * first. 9 | * 10 | * @author Emiel Bruijntjes 11 | * @copyright 2019 Copernica BV 12 | */ 13 | 14 | /** 15 | * Begin of namespace 16 | */ 17 | namespace Php { 18 | 19 | /** 20 | * Class definition 21 | */ 22 | class State 23 | { 24 | private: 25 | /** 26 | * The current exception that was active when state was registered 27 | * @var zend_object 28 | */ 29 | zend_object *_exception; 30 | 31 | /** 32 | * Helper method to check if a zend-class is an instance of a certain class 33 | * @param entry the class entry to check 34 | * @param required the required class entry 35 | * @return bool 36 | */ 37 | static bool instanceof(const zend_class_entry *entry, const zend_class_entry *required) 38 | { 39 | // check the class name 40 | if (entry == required) return true; 41 | 42 | // is there a base class? 43 | if (entry->parent == nullptr) return false; 44 | 45 | // check the parent 46 | return instanceof(entry->parent, required); 47 | } 48 | 49 | /** 50 | * Helper method to check if a zend-object is an instance of a certain class 51 | * @param object the object to check 52 | * @param required required class entry 53 | * @return bool 54 | */ 55 | static bool instanceof(const zend_object *object, zend_class_entry *required) 56 | { 57 | return instanceof(object->ce, required); 58 | } 59 | 60 | 61 | public: 62 | /** 63 | * Constructor 64 | */ 65 | State() : _exception(EG(exception)) {} 66 | 67 | /** 68 | * Destructor 69 | */ 70 | virtual ~State() = default; 71 | 72 | /** 73 | * Rethrow the exception so that it ends up in the extension 74 | * 75 | * When this method returns, it means that no exception occured, 76 | * and the call to PHP space was a success. Otherwise it throws 77 | * an exception. Note that this is not exactly in line with our 78 | * coding convention that says that methods are not supposed to 79 | * throw exceptions. 80 | * 81 | * @throw Throwable 82 | */ 83 | void rethrow() 84 | { 85 | // is an exception now active 86 | zend_object *current = EG(exception); 87 | 88 | // if no exception is active 89 | if (current == nullptr) return; 90 | 91 | // or if the exception did not change 92 | if (current == _exception) return; 93 | 94 | // an exception occured, this can be a PHP error or a PHP exception 95 | if (instanceof(current, zend_ce_error)) throw RethrowableError(current); 96 | 97 | // otherwise we wrap the exception 98 | throw RethrowableException(current); 99 | } 100 | }; 101 | 102 | /** 103 | * End of namespace 104 | */ 105 | } 106 | 107 | -------------------------------------------------------------------------------- /zend/stream.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Stream.cpp 3 | * 4 | * Implementation file for the stream class. 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2019 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Constructor 22 | * @param value value to be wrapped 23 | * @throws std::runtime_error 24 | */ 25 | Stream::Stream(const Value &value) : _value(value) 26 | { 27 | // get the stream object 28 | php_stream_from_zval_no_verify(_stream, _value._val); 29 | 30 | // was this indeed a stream? 31 | if (_stream == nullptr) throw std::runtime_error("variable does not hold a stream"); 32 | } 33 | 34 | /** 35 | * Destructor 36 | */ 37 | Stream::~Stream() {} 38 | 39 | /** 40 | * Size of the read-buffer (number of bytes that have already been read 41 | * from the underlying filesystem, but that are not yet passed to php space) 42 | * @return size_t 43 | */ 44 | size_t Stream::readbuffer() const 45 | { 46 | // do the math 47 | return _stream->writepos - _stream->readpos; 48 | } 49 | 50 | /** 51 | * Get access to the internal filedescriptor 52 | * Note that not every stream is always associated with a filedescriptor, 53 | * in which case this function returns -1 54 | * @return int 55 | */ 56 | int Stream::fd() const 57 | { 58 | // the return value 59 | int retval = -1; 60 | 61 | // cast the stream to a filedescriptor, the cast-internal parameter is supposed to be to get 62 | // rid of warnings about buffered data (this code was copied from streamfuncs.c). We use 63 | // "FOR_SELECT" casting, as that is the most simple operations (without "FOR_SELECT" it flushes too) 64 | auto result = php_stream_cast(_stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void **)&retval, 0); 65 | 66 | // on failure we return -1 67 | return result == SUCCESS ? retval : -1; 68 | } 69 | 70 | /** 71 | * End of namespace 72 | */ 73 | } 74 | 75 | -------------------------------------------------------------------------------- /zend/streambuf.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * StreamBuf.cpp 3 | * 4 | * Implementation file for the StreamBuf class 5 | * 6 | * @see http://www.mr-edd.co.uk/blog/beginners_guide_streambuf 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | #include "includes.h" 12 | 13 | /** 14 | * Set up namespace 15 | */ 16 | namespace Php { 17 | 18 | /** 19 | * Called when the internal buffer should be synchronized 20 | * @return int 21 | */ 22 | int StreamBuf::sync() 23 | { 24 | // current buffer size 25 | size_t size = pptr() - pbase(); 26 | 27 | // is this the error stream or the regular output stream? 28 | if (_error) 29 | { 30 | // write to error (the zend_error() method is a varargs function, 31 | // which means that we have to include a printf() like format as first 32 | // parameter. We can not specify pbase() directly, because (1) it is 33 | // not null terminated and (2) it could contain % signs and allow all 34 | // sorts of buffer overflows. 35 | zend_error(_error, "%.*s", (int)size, pbase()); 36 | } 37 | else 38 | { 39 | // write to zend 40 | zend_write(pbase(), size); 41 | } 42 | 43 | // reset the buffer 44 | pbump(-size); 45 | 46 | // done 47 | return 0; 48 | } 49 | 50 | /** 51 | * End namespace 52 | */ 53 | } 54 | 55 | -------------------------------------------------------------------------------- /zend/streams.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Streams.cpp 3 | * 4 | * Implementation of the streams 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 Copernica BV 8 | */ 9 | #include "includes.h" 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Some static buffers for writing data 18 | * @var StreamBuf 19 | */ 20 | static thread_local StreamBuf bufOut (0); 21 | static thread_local StreamBuf bufError (E_ERROR); 22 | static thread_local StreamBuf bufWarning (E_WARNING); 23 | static thread_local StreamBuf bufNotice (E_NOTICE); 24 | static thread_local StreamBuf bufDeprecated (E_DEPRECATED); 25 | 26 | /** 27 | * Create the actual steams 28 | * @var std::ostream 29 | */ 30 | thread_local std::ostream out (&bufOut); 31 | thread_local std::ostream error (&bufError); 32 | thread_local std::ostream warning (&bufWarning); 33 | thread_local std::ostream notice (&bufNotice); 34 | thread_local std::ostream deprecated (&bufDeprecated); 35 | 36 | /** 37 | * End namespace 38 | */ 39 | } 40 | 41 | -------------------------------------------------------------------------------- /zend/stringmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * StringMember.h 3 | * 4 | * Implementation for a property that is initially set to a string value 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class StringMember : public Member 19 | { 20 | private: 21 | /** 22 | * The value 23 | * @var string 24 | */ 25 | std::string _value; 26 | 27 | public: 28 | /** 29 | * Constructor 30 | * @param name 31 | * @param value 32 | * @param size 33 | * @param flags 34 | */ 35 | StringMember(const char *name, const char *value, size_t size, int flags) : Member(name, flags), _value(value, size) {} 36 | 37 | /** 38 | * Constructor 39 | * @param name 40 | * @param value 41 | * @param flags 42 | */ 43 | StringMember(const char *name, const char *value, int flags) : StringMember(name, value, ::strlen(value), flags) {} 44 | 45 | /** 46 | * Constructor 47 | * @param name 48 | * @param value 49 | * @param flags 50 | */ 51 | StringMember(const char *name, const std::string &value, int flags) : Member(name, flags), _value(value) {} 52 | 53 | /** 54 | * Destructor 55 | */ 56 | virtual ~StringMember() {} 57 | 58 | /** 59 | * Virtual method to declare class constant 60 | * @param entry Class entry 61 | */ 62 | virtual void constant(struct _zend_class_entry *entry) override 63 | { 64 | zend_declare_class_constant_stringl(entry, _name.c_str(), _name.size(), _value.c_str(), _value.size()); 65 | } 66 | 67 | /** 68 | * Virtual method to declare the property 69 | * @param entry Class entry 70 | */ 71 | virtual void declare(struct _zend_class_entry *entry) override 72 | { 73 | zend_declare_property_stringl(entry, _name.c_str(), _name.size(), (char *)_value.c_str(), _value.size(), _flags); 74 | } 75 | }; 76 | 77 | /** 78 | * End of namespace 79 | */ 80 | } 81 | 82 | -------------------------------------------------------------------------------- /zend/super.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Super.cpp 3 | * 4 | * @copyright 2014 Copernica BV 5 | * @author Emiel Bruijntjes 6 | */ 7 | #include "includes.h" 8 | #include "string.h" 9 | 10 | /** 11 | * Set up namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * A number of super-globals are always accessible 17 | */ 18 | Super POST (TRACK_VARS_POST, "_POST"); 19 | Super GET (TRACK_VARS_GET, "_GET"); 20 | Super COOKIE (TRACK_VARS_COOKIE, "_COOKIE"); 21 | Super SERVER (TRACK_VARS_SERVER, "_SERVER"); 22 | Super ENV (TRACK_VARS_ENV, "_ENV"); 23 | Super FILES (TRACK_VARS_FILES, "_FILES"); 24 | Super REQUEST (TRACK_VARS_REQUEST, "_REQUEST"); 25 | 26 | /** 27 | * Convert object to a value 28 | * @return Value 29 | */ 30 | Value Super::value() 31 | { 32 | // call zend_is_auto_global to ensure that the just-in-time globals are loaded 33 | if (_name) { 34 | // make the variable an auto global 35 | zend_is_auto_global(String{ _name }); 36 | 37 | // reset because we only need to do this once 38 | _name = nullptr; 39 | } 40 | 41 | // create a value object that wraps around the actual zval 42 | return &PG(http_globals)[_index]; 43 | } 44 | 45 | /** 46 | * End namespace 47 | */ 48 | } 49 | 50 | -------------------------------------------------------------------------------- /zend/throwable.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Throwable.cpp 3 | * 4 | * Implementation file for the Throwable class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2019 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Begin of namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Helper function converts an object to a string 22 | * @return std::string 23 | */ 24 | static std::string convert(zend_object *object) 25 | { 26 | // the result value from zend and the object zval 27 | zval tmp, properties; 28 | 29 | // retrieve the object properties 30 | ZVAL_OBJ(&properties, object); 31 | 32 | // retrieve the message, filename, error code and line number 33 | #if PHP_VERSION_ID < 80000 34 | auto message = zval_get_string(zend_read_property(Z_OBJCE(properties), &properties, ZEND_STRL("message"), 1, &tmp)); 35 | #else 36 | auto message = zval_get_string(zend_read_property(Z_OBJCE(properties), object, ZEND_STRL("message"), 1, &tmp)); 37 | #endif 38 | 39 | // copy message to a string 40 | std::string result(ZSTR_VAL(message), ZSTR_LEN(message)); 41 | 42 | // clean up message string 43 | zend_string_release(message); 44 | 45 | // done 46 | return result; 47 | } 48 | 49 | /** 50 | * Another protected constructor 51 | * @param object 52 | */ 53 | Throwable::Throwable(zend_object *object) : std::runtime_error(convert(object)) 54 | { 55 | // the result value from zend and the object zval 56 | zval result, properties; 57 | 58 | // retrieve the object properties 59 | ZVAL_OBJ(&properties, object); 60 | 61 | // retrieve the error code 62 | #if PHP_VERSION_ID < 80000 63 | _code = zval_get_long(zend_read_property(Z_OBJCE(properties), &properties, ZEND_STRL("code"), 1, &result)); 64 | #else 65 | _code = zval_get_long(zend_read_property(Z_OBJCE(properties), object, ZEND_STRL("code"), 1, &result)); 66 | #endif 67 | } 68 | 69 | /** 70 | * End of namespace 71 | */ 72 | } 73 | 74 | -------------------------------------------------------------------------------- /zend/valueiterator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * ValueIterator.cpp 3 | * 4 | * Implementation of the value iterator 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2014 Copernica BV 8 | */ 9 | #include "includes.h" 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Constructor 18 | * @param impl Implementation iterator 19 | */ 20 | ValueIterator::ValueIterator(ValueIteratorImpl *impl) : _impl(impl) {} 21 | 22 | /** 23 | * Copy constructor 24 | * @param that 25 | */ 26 | ValueIterator::ValueIterator(const ValueIterator &that) : _impl(that._impl->clone()) {} 27 | 28 | /** 29 | * Destructor 30 | */ 31 | ValueIterator::~ValueIterator() = default; 32 | 33 | /** 34 | * Increment position 35 | * @return ValueIterator 36 | */ 37 | ValueIterator &ValueIterator::operator++() 38 | { 39 | // increment implementation 40 | _impl->increment(); 41 | 42 | // done 43 | return *this; 44 | } 45 | 46 | /** 47 | * Decrement position 48 | * @return ValueIterator 49 | */ 50 | ValueIterator &ValueIterator::operator--() 51 | { 52 | // decrement implementation 53 | _impl->decrement(); 54 | 55 | // done 56 | return *this; 57 | } 58 | 59 | /** 60 | * Compare with other iterator 61 | * @param that 62 | * @return bool 63 | */ 64 | bool ValueIterator::operator==(const ValueIterator &that) const 65 | { 66 | return _impl->equals(that._impl.get()); 67 | } 68 | 69 | /** 70 | * Compare with other iterator 71 | * @param that 72 | * @return bool 73 | */ 74 | bool ValueIterator::operator!=(const ValueIterator &that) const 75 | { 76 | return !_impl->equals(that._impl.get()); 77 | } 78 | 79 | /** 80 | * Derefecence, this returns a std::pair with the current key and value 81 | * @return std::pair 82 | */ 83 | const std::pair &ValueIterator::operator*() const 84 | { 85 | return _impl->current(); 86 | } 87 | 88 | /** 89 | * Dereference, this returns a std::pair with the current key and value 90 | * @return std::pair 91 | */ 92 | const std::pair *ValueIterator::operator->() const 93 | { 94 | return &_impl->current(); 95 | } 96 | 97 | /** 98 | * End namespace 99 | */ 100 | } 101 | 102 | -------------------------------------------------------------------------------- /zend/valueiteratorimpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ValueIteratorImpl.h 3 | * 4 | * Interface that describes what an implementation of a value iterator should 5 | * look like. This is an internal class that extension developers do not 6 | * need. It is used internally inside the ValueIterator class. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2014 Copernica BV 10 | */ 11 | 12 | /** 13 | * Set up namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Class definition 19 | */ 20 | class ValueIteratorImpl 21 | { 22 | public: 23 | /** 24 | * Constructor 25 | */ 26 | ValueIteratorImpl() {} 27 | 28 | /** 29 | * Destructor 30 | */ 31 | virtual ~ValueIteratorImpl() {} 32 | 33 | /** 34 | * Clone the object 35 | * @return ValueIteratorImpl* 36 | */ 37 | virtual ValueIteratorImpl *clone() = 0; 38 | 39 | /** 40 | * Increment position (pre-increment) 41 | * @return bool 42 | */ 43 | virtual bool increment() = 0; 44 | 45 | /** 46 | * Decrement position (pre-decrement) 47 | * @return bool 48 | */ 49 | virtual bool decrement() = 0; 50 | 51 | /** 52 | * Compare with other iterator 53 | * @param that 54 | * @return bool 55 | */ 56 | virtual bool equals(const ValueIteratorImpl *that) const = 0; 57 | 58 | /** 59 | * Derefecence, this returns a std::pair with the current key and value 60 | * @return std::pair 61 | */ 62 | virtual const std::pair ¤t() const = 0; 63 | }; 64 | 65 | /** 66 | * End namespace 67 | */ 68 | } 69 | 70 | -------------------------------------------------------------------------------- /zend/zendcallable.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * callable.cpp 3 | * 4 | * A wrapper to handle a callback coming from 5 | * within PHP 6 | * 7 | * @author Martijn Otto 8 | * @copyright 2016 Copernica B.V. 9 | */ 10 | #include "includes.h" 11 | 12 | /** 13 | * Start namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Retrieve pointer to the object 19 | * 20 | * @param execute_data The current execution scope 21 | * @return Pointer (as void because this cannot be templated!) 22 | */ 23 | Base *ZendCallable::instance(struct _zend_execute_data *execute_data) 24 | { 25 | // find the object implementation and retrieve the base object 26 | return ObjectImpl::find(getThis())->object(); 27 | } 28 | 29 | /** 30 | * Check whether we have received valid parameters 31 | * 32 | * If this function returns false a warning will have been 33 | * generated and the return value has been set to NULL. 34 | * 35 | * @param execute_data The current execution scope 36 | * @param return_value The return value to set on failure 37 | */ 38 | bool ZendCallable::valid(struct _zend_execute_data *execute_data, struct _zval_struct *return_value) 39 | { 40 | // how many parameters are required and how many to we have? 41 | auto required = execute_data->func->common.required_num_args; 42 | auto provided = ZEND_NUM_ARGS(); 43 | 44 | // if we have the required minimum number of arguments there is no problem 45 | if (provided >= required) return true; 46 | 47 | // retrieve the function name to display the error 48 | auto *name = get_active_function_name(); 49 | 50 | // we do not have enough input parameters, show a warning about this 51 | Php::warning << name << "() expects at least " << required << " parameter(s), " << provided << " given" << std::flush; 52 | 53 | // set the return value to NULL 54 | RETVAL_NULL(); 55 | 56 | // we are not in a valid state 57 | return false; 58 | } 59 | 60 | /** 61 | * Retrieve the input parameters for the function 62 | * 63 | * @param execute_data The current execution scope 64 | * @return The input parameters 65 | */ 66 | Parameters ZendCallable::parameters(struct _zend_execute_data *execute_data) 67 | { 68 | // parse and return the parameters 69 | return ParametersImpl{ getThis(), ZEND_NUM_ARGS() }; 70 | } 71 | 72 | /** 73 | * Handle throwables 74 | * @param throwable The object to handle 75 | */ 76 | void ZendCallable::handle(Throwable &throwable) 77 | { 78 | // pass to user space 79 | throwable.rethrow(); 80 | } 81 | 82 | /** 83 | * Yield (return) the given value 84 | * 85 | * @param return_value The return_value to set 86 | * @param value The value to return to PHP 87 | */ 88 | void ZendCallable::yield(struct _zval_struct *return_value, std::nullptr_t value) 89 | { 90 | // set the return value to null 91 | RETVAL_NULL(); 92 | } 93 | 94 | /** 95 | * Yield (return) the given value 96 | * 97 | * @param return_value The return_value to set 98 | * @param value The value to return to PHP 99 | */ 100 | void ZendCallable::yield(struct _zval_struct *return_value, const Php::Value &value) 101 | { 102 | // copy the value over to the return value 103 | RETVAL_ZVAL(value._val, 1, 0); 104 | } 105 | 106 | /** 107 | * End namespace 108 | */ 109 | } 110 | -------------------------------------------------------------------------------- /zend/zval.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Zval.cpp 3 | * 4 | * Implementation for the Zval class 5 | * 6 | * @author Toon Schoenmakers 7 | * @copyright 2013, 2014 Copernica BV 8 | */ 9 | 10 | /** 11 | * Dependencies 12 | */ 13 | #include "includes.h" 14 | 15 | /** 16 | * Set up namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * In case this is a reference, dereference it into a zval.. In case it isn't 22 | * the actual value is returned. 23 | * @return struct _zval_struct* 24 | */ 25 | struct _zval_struct *Zval::dereference() const 26 | { 27 | // first cast ourselves to a zval struct 28 | struct _zval_struct *self = const_cast(reinterpret_cast(&_buffer)); 29 | 30 | // if we're not a reference we just return ourselves as is 31 | if (((Type) Z_TYPE_P(self)) != Type::Reference) return self; 32 | 33 | // otherwise we simply retrieve the value of the reference 34 | return Z_REFVAL_P(self); 35 | } 36 | 37 | /** 38 | * End namespace 39 | */ 40 | } --------------------------------------------------------------------------------