diff options
-rw-r--r-- | Makefile | 146 | ||||
-rw-r--r-- | include/arrayaccess.h | 94 | ||||
-rw-r--r-- | include/class.h | 36 | ||||
-rw-r--r-- | include/classbase.h | 14 | ||||
-rw-r--r-- | include/countable.h | 8 | ||||
-rw-r--r-- | phpcpp.h | 1 | ||||
-rw-r--r-- | src/callable.cpp | 5 | ||||
-rw-r--r-- | src/classbase.cpp | 6 | ||||
-rw-r--r-- | src/countable.cpp | 32 | ||||
-rw-r--r-- | src/includes.h | 1 |
10 files changed, 227 insertions, 116 deletions
@@ -1,141 +1,141 @@ # -# PHP-CPP Makefile +# PHP-CPP Makefile # -# This makefile has a user friendly order: the top part of this file contains -# all variable settings that you may alter to suit your own system, while at -# the bottom you will find instructions for the compiler in which you will -# probably not have to make any changes -# +# This makefile has a user friendly order: the top part of this file contains +# all variable settings that you may alter to suit your own system, while at +# the bottom you will find instructions for the compiler in which you will +# probably not have to make any changes +# # -# Zend header files +# Zend header files # -# The variable PHP_DIR contains the location on your system where the regular -# header files of the Zend engine can be found. Usually this is either -# /usr/include/php5 or /usr/local/include/php5. Inside this directory you -# will find sub-directories named TSRM, Zend, ext and main. +# The variable PHP_DIR contains the location on your system where the regular +# header files of the Zend engine can be found. Usually this is either +# /usr/include/php5 or /usr/local/include/php5. Inside this directory you +# will find sub-directories named TSRM, Zend, ext and main. # -PHP_DIR = /usr/include/php5 +PHP_DIR = /usr/include/php5 # -# Installation directory +# Installation directory # -# When you install the PHP-CPP library, it will place a number of C++ *.h -# header files in your system include directory, and a libphpcpp.so shared -# library file in your system libraries directory. Most users set this to -# the regular /usr/include and /usr/lib directories, or /usr/local/include -# and /usr/local/lib. You can of course change it to whatever suits you best -# +# When you install the PHP-CPP library, it will place a number of C++ *.h +# header files in your system include directory, and a libphpcpp.so shared +# library file in your system libraries directory. Most users set this to +# the regular /usr/include and /usr/lib directories, or /usr/local/include +# and /usr/local/lib. You can of course change it to whatever suits you best +# -INSTALL_PREFIX = /usr -INSTALL_HEADERS = ${INSTALL_PREFIX}/include -INSTALL_LIB = ${INSTALL_PREFIX}/lib +INSTALL_PREFIX = /usr +INSTALL_HEADERS = ${INSTALL_PREFIX}/include +INSTALL_LIB = ${INSTALL_PREFIX}/lib # -# Name of the target library name +# Name of the target library name # -# The PHP-CPP library will be installed on your system as libphpcpp.so. -# This is a brilliant name. If you want to use a different name for it, -# you can change that here +# The PHP-CPP library will be installed on your system as libphpcpp.so. +# This is a brilliant name. If you want to use a different name for it, +# you can change that here # -RESULT = libphpcpp.so +RESULT = libphpcpp.so # -# Compiler +# Compiler # -# By default, the GNU C++ compiler is used. If you want to use a different -# compiler, you can change that here. You can change this for both the -# compiler (the program that turns the c++ files into object files) and for -# the linker (the program that links all object files into a single .so -# library file. By default, g++ (the GNU C++ compiler) is used for both. +# By default, the GNU C++ compiler is used. If you want to use a different +# compiler, you can change that here. You can change this for both the +# compiler (the program that turns the c++ files into object files) and for +# the linker (the program that links all object files into a single .so +# library file. By default, g++ (the GNU C++ compiler) is used for both. # -COMPILER = g++ -LINKER = g++ +COMPILER = g++ +LINKER = g++ # -# Compiler flags +# Compiler flags # -# This variable holds the flags that are passed to the compiler. By default, -# we include the -O2 flag. This flag tells the compiler to optimize the code, -# but it makes debugging more difficult. So if you're debugging your application, -# you probably want to remove this -O2 flag. At the same time, you can then -# add the -g flag to instruct the compiler to include debug information in -# the library (but this will make the final libphpcpp.so file much bigger, so -# you want to leave that flag out on production servers). +# This variable holds the flags that are passed to the compiler. By default, +# we include the -O2 flag. This flag tells the compiler to optimize the code, +# but it makes debugging more difficult. So if you're debugging your application, +# you probably want to remove this -O2 flag. At the same time, you can then +# add the -g flag to instruct the compiler to include debug information in +# the library (but this will make the final libphpcpp.so file much bigger, so +# you want to leave that flag out on production servers). # -COMPILER_FLAGS = -Wall -c -I. -I${PHP_DIR} -I${PHP_DIR}/main -I${PHP_DIR}/ext -I${PHP_DIR}/Zend -I${PHP_DIR}/TSRM -O2 -std=c++11 -fpic -o +COMPILER_FLAGS = -Wall -c -I. -I${PHP_DIR} -I${PHP_DIR}/main -I${PHP_DIR}/ext -I${PHP_DIR}/Zend -I${PHP_DIR}/TSRM -g -std=c++11 -fpic -o # -# Linker flags +# Linker flags # -# Just like the compiler, the linker can have flags too. The default flag -# is probably the only one you need. +# Just like the compiler, the linker can have flags too. The default flag +# is probably the only one you need. # -LINKER_FLAGS = -shared +LINKER_FLAGS = -shared # -# Command to remove files, copy files and create directories. +# Command to remove files, copy files and create directories. # -# I've never encountered a *nix environment in which these commands do not work. -# So you can probably leave this as it is +# I've never encountered a *nix environment in which these commands do not work. +# So you can probably leave this as it is # -RM = rm -f -CP = cp -f -MKDIR = mkdir -p +RM = rm -f +CP = cp -f +MKDIR = mkdir -p # -# The source files +# The source files # -# For this we use a special Makefile function that automatically scans the -# src/ directory for all *.cpp files. No changes are probably necessary here +# For this we use a special Makefile function that automatically scans the +# src/ directory for all *.cpp files. No changes are probably necessary here # -SOURCES = $(wildcard src/*.cpp) +SOURCES = $(wildcard src/*.cpp) # -# The object files +# The object files # -# The intermediate object files are generated by the compiler right before -# the linker turns all these object files into the libphpcpp.so shared library. -# We also use a Makefile function here that takes all source files. +# The intermediate object files are generated by the compiler right before +# the linker turns all these object files into the libphpcpp.so shared library. +# We also use a Makefile function here that takes all source files. # -OBJECTS = $(SOURCES:%.cpp=%.o) +OBJECTS = $(SOURCES:%.cpp=%.o) # -# End of the variables section. Here starts the list of instructions and -# dependencies that are used by the compiler. +# End of the variables section. Here starts the list of instructions and +# dependencies that are used by the compiler. # -all: ${OBJECTS} ${RESULT} +all: ${OBJECTS} ${RESULT} ${RESULT}: ${OBJECTS} - ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} + ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} clean: - ${RM} ${OBJECTS} ${RESULT} + ${RM} ${OBJECTS} ${RESULT} ${OBJECTS}: - ${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp} + ${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp} install: - ${MKDIR} ${INSTALL_HEADERS}/phpcpp - ${CP} phpcpp.h ${INSTALL_HEADERS} - ${CP} include/*.h ${INSTALL_HEADERS}/phpcpp - ${CP} ${RESULT} ${INSTALL_LIB} + ${MKDIR} ${INSTALL_HEADERS}/phpcpp + ${CP} phpcpp.h ${INSTALL_HEADERS} + ${CP} include/*.h ${INSTALL_HEADERS}/phpcpp + ${CP} ${RESULT} ${INSTALL_LIB} diff --git a/include/arrayaccess.h b/include/arrayaccess.h new file mode 100644 index 0000000..6ee3163 --- /dev/null +++ b/include/arrayaccess.h @@ -0,0 +1,94 @@ +/** + * ArrayAccess.h + * + * "Interface" that can be "implemented" by your class. If you do, you + * create your class like this: + * + * class MyClass : public Php::Base, public Php::ArrayAccess { ... } + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2014 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class ArrayAccess +{ +public: + /** + * Check if a member is set + * @param key + * @return bool + */ + virtual bool offsetExists(const Php::Value &key) = 0; + + /** + * Set a member + * @param key + * @param value + */ + virtual void offsetSet(const Php::Value &key, const Php::Value &value) = 0; + + /** + * Retrieve a member + * @param key + * @return value + */ + virtual Php::Value offsetGet(const Php::Value &key) = 0; + + /** + * Remove a member + * @param key + */ + virtual void offsetUnset(const Php::Value &key) = 0; + + /** + * Alternative offsetExists as it is initially called + * @param params + * @return bool + */ + virtual Php::Value offsetExists(Php::Parameters ¶ms) + { + return offsetExists(params[0]); + } + + /** + * Alternative set member function as it is initially called + * @param params + */ + virtual void offsetSet(const Php::Parameters ¶ms) + { + offsetSet(params[0], params[1]); + } + + /** + * Alternative retrieve member function that is initially called + * @param params + * @return value + */ + virtual Php::Value offsetGet(Php::Parameters ¶ms) + { + return offsetGet(params[0]); + } + + /** + * Alternative function to remove a member that is initally called + * @param params + */ + virtual void offsetUnset(Php::Parameters ¶ms) + { + return offsetUnset(params[0]); + } +}; + +/** + * End namespace + */ +} + diff --git a/include/class.h b/include/class.h index a22b9a8..3326507 100644 --- a/include/class.h +++ b/include/class.h @@ -16,6 +16,12 @@ */ /** + * Zend/SPL interfaces that we support + */ +extern struct _zend_class_entry *spl_ce_Countable; +extern struct _zend_class_entry *spl_ce_ArrayAccess; + +/** * Set up namespace */ namespace Php { @@ -38,7 +44,35 @@ public: Class(const char *name) : ClassBase(name) { // check for special classes - if (std::is_base_of<Countable, T>::value) ClassBase::interface(Countable::implementation()); + if (std::is_base_of<Countable, T>::value) + { + // register the interface (we register a pointer-to-a-pointer here, + // because when this code runs (during the get_module() call), the + // interfaces are not yet initialized by the zend engine, this + // happens later when the all classes are registered (after the + // get_module() call) + interface(&spl_ce_Countable); + + // add the count method + method("count", &T::count, {}); + } + + // check for special classes + if (std::is_base_of<ArrayAccess, T>::value) + { + // register the interface (we register a pointer-to-a-pointer here, + // because when this code runs (during the get_module() call), the + // interfaces are not yet initialized by the zend engine, this + // happens later when the all classes are registered (after the + // get_module() call) + interface(&spl_ce_ArrayAccess); + + // add the count method + method("count", &T::offsetSet); + method("count", &T::offsetGet); + method("count", &T::offsetUnset); + method("count", &T::offsetExists); + } } /** diff --git a/include/classbase.h b/include/classbase.h index 3792fdb..92e637d 100644 --- a/include/classbase.h +++ b/include/classbase.h @@ -19,6 +19,7 @@ */ struct _zend_object_value; struct _zend_object_handlers; +struct _zend_class_entry; /** * Set up namespace @@ -66,6 +67,7 @@ public: _type(that._type), _methods(that._methods), _members(that._members), + _interfaces(that._interfaces), _entry(nullptr) {} /** @@ -77,6 +79,7 @@ public: _type(that._type), _methods(std::move(that._methods)), _members(std::move(that._members)), + _interfaces(std::move(that._interfaces)), _entry(that._entry) { // other entry are invalid now (not that it is used..., class objects are @@ -188,9 +191,16 @@ protected: * It does however make sense to support implementing extension-specific * interface. We may add this feature in the future. * + * This method is called _during_ the get_module() call when all classes + * are defined by the extension. However, at that time the Zend engine has + * not yet initialized the zend_class_entry's with the interface addresses. + * That's why we ask for a pointer-to-a-pointer. Later, when the classes + * are really registered, the Zend engine is with registering interfaces + * and the pointers point to a valid variable. + * * @param interface */ - void interface(struct _zend_class_entry *interface) + void interface(struct ::_zend_class_entry **interface) { // register the interface _interfaces.push_back(interface); @@ -274,7 +284,7 @@ private: * All interfaces that are implemented * @var std::list */ - std::list<struct _zend_class_entry*> _interfaces; + std::list<struct ::_zend_class_entry**> _interfaces; }; diff --git a/include/countable.h b/include/countable.h index 12d87d5..1b99463 100644 --- a/include/countable.h +++ b/include/countable.h @@ -25,17 +25,11 @@ class Countable { public: /** - * Implementation of the countable interface - * @return zend_class_entry* - * @internal - */ - static struct _zend_class_entry *implementation(); - - /** * Retrieve the number of items in the class * @return Value */ virtual Value count() = 0; + }; /** @@ -40,6 +40,7 @@ #include <phpcpp/modifiers.h> #include <phpcpp/base.h> #include <phpcpp/countable.h> +#include <phpcpp/arrayaccess.h> #include <phpcpp/classtype.h> #include <phpcpp/classbase.h> #include <phpcpp/class.h> diff --git a/src/callable.cpp b/src/callable.cpp index 66333d5..5229722 100644 --- a/src/callable.cpp +++ b/src/callable.cpp @@ -76,6 +76,9 @@ void Callable::initialize(zend_function_entry *entry, const char *classname, int entry->num_args = _argc; entry->flags = flags; + std::cout << entry->fname << " num_args " << entry->num_args << std::endl; + std::cout << entry->fname << " flags " << entry->flags << std::endl; + // we should fill the first argument as well #if PHP_VERSION_ID >= 50400 initialize((zend_internal_function_info *)entry->arg_info, classname); @@ -101,6 +104,8 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna info->required_num_args = _required; info->_type_hint = (unsigned char)_return; + std::cout << "required_num_args " << info->required_num_args << std::endl; + // we do not support return-by-reference info->return_reference = false; diff --git a/src/classbase.cpp b/src/classbase.cpp index 19ac6bc..48746ec 100644 --- a/src/classbase.cpp +++ b/src/classbase.cpp @@ -248,7 +248,11 @@ void ClassBase::initialize(const std::string &prefix) _entry->ce_flags = (int)_type; // mark the interfaces as being implemented - for (auto &interface : _interfaces) zend_do_implement_interface(_entry, interface); + for (auto &interface : _interfaces) + { + std::cout << "interface: " << interface << std::endl; + zend_do_implement_interface(_entry, *interface); + } // declare all member variables for (auto &member : _members) member->initialize(_entry); diff --git a/src/countable.cpp b/src/countable.cpp deleted file mode 100644 index 6182afd..0000000 --- a/src/countable.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Countable.cpp - * - * Implementation of the Countable interface - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2014 Copernica BV - */ -#include "includes.h" - -#include "spl/spl_iterators.h" - -/** - * Set up namespace - */ -namespace Php { - -/** - * Implementation of the countable interface - * @return zend_class_entry* - * @internal - */ -struct _zend_class_entry *Countable::implementation() -{ - return spl_ce_Countable; -} - -/** - * End namespace - */ -} - diff --git a/src/includes.h b/src/includes.h index 60783eb..e9718f3 100644 --- a/src/includes.h +++ b/src/includes.h @@ -59,6 +59,7 @@ #include "../include/modifiers.h" #include "../include/base.h" #include "../include/countable.h" +#include "../include/arrayaccess.h" #include "../include/classtype.h" #include "../include/classbase.h" #include "../include/class.h" |