diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-02-28 10:25:01 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-02-28 10:25:01 +0100 |
commit | 71055ebdea1e8eec30747a04f36e0c10e750bff5 (patch) | |
tree | 18ed63d5fe64a936c284a38d4f72921a4ddc97df /src | |
parent | 85349bbb642a83012a7d0dbccde8b7c1eea1b914 (diff) |
a lot of refactoring, to make it much easier to define classes in an extension
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/callable.cpp (renamed from src/function.cpp) | 52 | ||||
-rw-r--r-- | src/callable.h | 121 | ||||
-rw-r--r-- | src/class.cpp | 10 | ||||
-rw-r--r-- | src/classbase.cpp (renamed from src/classinfo.cpp) | 131 | ||||
-rw-r--r-- | src/extension.cpp | 71 | ||||
-rw-r--r-- | src/function.h (renamed from src/nativefunction.h) | 16 | ||||
-rw-r--r-- | src/includes.h | 9 | ||||
-rw-r--r-- | src/member.cpp | 7 | ||||
-rw-r--r-- | src/members.cpp | 140 | ||||
-rw-r--r-- | src/method.h | 104 | ||||
-rw-r--r-- | src/methodbase.cpp | 24 | ||||
-rw-r--r-- | src/methodmember.h | 111 | ||||
-rw-r--r-- | src/methods.h | 114 |
14 files changed, 675 insertions, 237 deletions
diff --git a/src/Makefile b/src/Makefile index 069024d..64b4eb1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ CPP = g++ RM = rm -f PHP_DIR = /usr/include/php5 -CPP_FLAGS = -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 +CPP_FLAGS = -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 LD = g++ LD_FLAGS = -Wall -shared -O2 diff --git a/src/function.cpp b/src/callable.cpp index ba37022..d410c0b 100644 --- a/src/function.cpp +++ b/src/callable.cpp @@ -23,13 +23,13 @@ namespace Php { * @param tsrm_ls * @return integer */ -void invoke_function(INTERNAL_FUNCTION_PARAMETERS) +static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) { // find the function name const char *name = get_active_function_name(TSRMLS_C); // uncover the hidden pointer inside the function name - Function *function = HiddenPointer<Function>(name); + Callable *callable = HiddenPointer<Callable>(name); // wrap the return value Value result(return_value, true); @@ -41,7 +41,7 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS) try { // get the result - result = function->invoke(params); + result = callable->invoke(params); } catch (Php::OrigException &exception) { @@ -58,40 +58,6 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS) } /** - * Constructor - * @param name Name of the function - * @param min Min number of arguments - * @param max Max number of arguments - */ -Function::Function(const char *name, const std::initializer_list<Argument> &arguments) : _ptr(this, name) -{ - // construct vector for arguments - _argc = arguments.size(); - _argv = new zend_arg_info[_argc+1]; - - // counter - int i=1; - - // loop through the arguments - for (auto it = arguments.begin(); it != arguments.end(); it++) - { - // fill the arg info - it->fill(&_argv[i++]); - } - - // @todo find out number of required arguments - _required = _argc; -} - -/** - * Destructor - */ -Function::~Function() -{ - delete[] _argv; -} - -/** * Fill a function entry * * This method is called when the extension is registering itself, when the @@ -101,18 +67,18 @@ Function::~Function() * @param classname Optional class name * @param flags Is this a public property? */ -void Function::fill(zend_function_entry *entry, const char *classname, MemberModifier flags) const +void Callable::initialize(zend_function_entry *entry, const char *classname, int flags) const { // fill the members of the entity, and hide a pointer to the current object in the name - entry->fname = _ptr; - entry->handler = invoke_function; + entry->fname = (const char *)_ptr; + entry->handler = invoke_callable; entry->arg_info = _argv; entry->num_args = _argc; entry->flags = flags; // we should fill the first argument as well #if PHP_VERSION_ID >= 50400 - fill((zend_internal_function_info *)entry->arg_info, classname); + initialize((zend_internal_function_info *)entry->arg_info, classname); #endif } @@ -122,7 +88,7 @@ void Function::fill(zend_function_entry *entry, const char *classname, MemberMod * @param classname Optional classname */ #if PHP_VERSION_ID >= 50400 -void Function::fill(zend_internal_function_info *info, const char *classname) const +void Callable::initialize(zend_internal_function_info *info, const char *classname) const { // fill in all the members, note that return reference is false by default, // because we do not support returning references in PHP-CPP, although Zend @@ -133,7 +99,7 @@ void Function::fill(zend_internal_function_info *info, const char *classname) co // number of required arguments, and the expected return type info->required_num_args = _required; - info->_type_hint = _type; + info->_type_hint = _return; // we do not support return-by-reference info->return_reference = false; diff --git a/src/callable.h b/src/callable.h new file mode 100644 index 0000000..1b761ae --- /dev/null +++ b/src/callable.h @@ -0,0 +1,121 @@ +/** + * Callable.h + * + * Object represents a callable function or method that is defined with the CPP + * API. + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Forward definitions + */ +struct _zend_function_entry; +struct _zend_internal_function_info; + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class Callable +{ +public: + /** + * Constructor + * @param name Function or method name + * @param arguments Information about the arguments + */ + Callable(const char *name, const Arguments &arguments = {}) : _ptr(this, name) + { + // construct vector for arguments + _argc = arguments.size(); + _argv = new zend_arg_info[_argc+1]; + + // counter + int i=1; + + // loop through the arguments + for (auto it = arguments.begin(); it != arguments.end(); it++) + { + // fill the arg info + it->fill(&_argv[i++]); + } + + // @todo find out number of required arguments + _required = _argc; + } + + /** + * Destructor + */ + virtual ~Callable() + { + delete[] _argv; + } + + /** + * Method that gets called every time the function is executed + * @param params The parameters that were passed + * @return Variable Return value + */ + virtual Value invoke(Parameters ¶ms) = 0; + + /** + * Fill a function entry + * @param entry Entry to be filled + * @param classname Optional class name + * @param flags Access flags + */ + void initialize(struct _zend_function_entry *entry, const char *classname = nullptr, int flags = 0) const; + + /** + * Fill function info + * @param info Info object to be filled + * @param classname Optional class name + */ + void initialize(struct _zend_internal_function_info *info, const char *classname = nullptr) const; + + +protected: + /** + * Hidden pointer to the name and the function + * @var HiddenPointer + */ + HiddenPointer<Callable> _ptr; + + /** + * Suggestion for the return type + * @var Type + */ + Type _return = nullType; + + /** + * Required number of arguments + * @var integer + */ + int _required = 0; + + /** + * Total number of arguments + * @var integer + */ + int _argc = 0; + + /** + * The arguments + * @var zend_arg_info[] + */ + struct _zend_arg_info *_argv = nullptr; + +}; + +/** + * End of namespace + */ +} + diff --git a/src/class.cpp b/src/class.cpp deleted file mode 100644 index 6263147..0000000 --- a/src/class.cpp +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Class.cpp - * - * Implementation for the class entry - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV - */ -#include "includes.h" - diff --git a/src/classinfo.cpp b/src/classbase.cpp index f96d724..2ad51b1 100644 --- a/src/classinfo.cpp +++ b/src/classbase.cpp @@ -1,10 +1,10 @@ /** - * ClassInfo.cpp + * ClassBase.cpp * - * Implementation for the class info + * Implementation of the ClassBase class. * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV + * @copyright 2014 Copernica BV */ #include "includes.h" @@ -62,9 +62,9 @@ static zend_object_value create_object(zend_class_entry *type TSRMLS_DC) // retrieve the classinfo object #if PHP_VERSION_ID >= 50400 - _ClassInfo *info = (_ClassInfo *)base->info.user.doc_comment; + ClassBase *info = (ClassBase *)base->info.user.doc_comment; #else - _ClassInfo *info = *((_ClassInfo **)base->doc_comment); + ClassBase *info = *((ClassBase **)base->doc_comment); #endif // store the class @@ -102,31 +102,70 @@ static zend_object_value create_object(zend_class_entry *type TSRMLS_DC) } /** - * Constructor - * @param name + * Destructor */ -_ClassInfo::_ClassInfo(const char *name) : _name(name), _entry(NULL) +ClassBase::~ClassBase() { + // destruct the entries + if (_entries) delete[] _entries; } /** - * Destructor + * Retrieve an array of zend_function_entry objects that hold the + * properties for each method. This method is called at extension + * startup time to register all methods. + * + * @param classname The class name + * @return zend_function_entry[] */ -_ClassInfo::~_ClassInfo() +const struct _zend_function_entry *ClassBase::entries() { + // already initialized? + if (_entries) return _entries; + + // allocate memory for the functions + _entries = new zend_function_entry[_methods.size() + 1]; + + // keep iterator counter + int i = 0; + + // loop through the functions + for (auto &method : _methods) + { + // retrieve entry + zend_function_entry *entry = &_entries[i++]; + + // let the function fill the entry + // @todo check flags for the method + method->initialize(entry, _name); + } + + // last entry should be set to all zeros + zend_function_entry *last = &_entries[i]; + + // all should be set to zero + memset(last, 0, sizeof(zend_function_entry)); + + // done + return _entries; } /** - * Initialize the class - * @param mixed Optional threading ID + * Initialize the class, given its name + * + * The module functions are registered on module startup, but classes are + * initialized afterwards. The Zend engine is a strange thing. Nevertheless, + * this means that this method is called after the module is already available. + * This function will inform the Zend engine about the existence of the + * class. */ -void _ClassInfo::initialize(TSRMLS_DC) +void ClassBase::initialize() { // the class entry zend_class_entry entry; // initialize the class entry - INIT_CLASS_ENTRY_EX(entry, _name.c_str(), _name.size(), methods()); + INIT_CLASS_ENTRY_EX(entry, _name.c_str(), _name.size(), entries()); // we need a special constructor entry.create_object = create_object; @@ -159,19 +198,69 @@ void _ClassInfo::initialize(TSRMLS_DC) _entry->doc_comment = (char *)wrapper; #endif - // initialize the entry - initialize(_entry); + // set access types flags for class + // @todo something with the flags, but before or after the register_internal_class? + //setFlags(entry, _type.getFlags()); + + // declare all properties + // @todo enable this +// _properties.initialize(_entry); +} + +/** + * Add a method to the class + * @param name Name of the method + * @param method The actual method + * @param flags Optional flags + * @param args Description of the supported arguments + */ +void ClassBase::add(const char *name, method_callback_0 callback, int flags, const Arguments &args) +{ + // add the method + _methods.insert(std::make_shared<Method>(name, callback, flags, args)); +} + +/** + * Add a method to the class + * @param name Name of the method + * @param method The actual method + * @param flags Optional flags + * @param args Description of the supported arguments + */ +void ClassBase::add(const char *name, method_callback_1 callback, int flags, const Arguments &args) +{ + // add the method + _methods.insert(std::make_shared<Method>(name, callback, flags, args)); } /** - * set access types flags for class + * Add a method to the class + * @param name Name of the method + * @param method The actual method + * @param flags Optional flags + * @param args Description of the supported arguments */ -void _ClassInfo::setFlags(struct _zend_class_entry *entry, int flags) { - entry->ce_flags |= flags; +void ClassBase::add(const char *name, method_callback_2 callback, int flags, const Arguments &args) +{ + // add the method + _methods.insert(std::make_shared<Method>(name, callback, flags, args)); } /** - * End of namespace + * Add a method to the class + * @param name Name of the method + * @param method The actual method + * @param flags Optional flags + * @param args Description of the supported arguments */ +void ClassBase::add(const char *name, method_callback_3 callback, int flags, const Arguments &args) +{ + // add the method + _methods.insert(std::make_shared<Method>(name, callback, flags, args)); } - + +/** + * End namespace + */ +} + diff --git a/src/extension.cpp b/src/extension.cpp index 5c5292e..dae5051 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -191,7 +191,7 @@ Extension::Extension(const char *name, const char *version, request_callback sta _entry->type = 0; // temporary or persistent module, will be filled by Zend engine _entry->handle = NULL; // dlopen() handle, will be filled by Zend engine _entry->module_number = 0; // module number will be filled in by Zend engine - _entry->build_id = ZEND_MODULE_BUILD_ID; // check if extension and zend engine are compatible + _entry->build_id = (char *)ZEND_MODULE_BUILD_ID; // check if extension and zend engine are compatible // things that only need to be initialized #ifdef ZTS @@ -215,29 +215,52 @@ Extension::~Extension() } /** - * Add a function to the library - * @param function Function object - * @return Function + * Add a native function directly to the extension + * @param name Name of the function + * @param function The function to add + * @param arguments Optional argument specification */ -Function *Extension::add(Function *function) +void Extension::add(const char *name, native_callback_0 function, const Arguments &arguments) { - // add the function to the map - _functions.insert(std::unique_ptr<Function>(function)); - - // the result is a pair with an iterator - return function; + // add a function + _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments))); +} + +/** + * Add a native function directly to the extension + * @param name Name of the function + * @param function The function to add + * @param arguments Optional argument specification + */ +void Extension::add(const char *name, native_callback_1 function, const Arguments &arguments) +{ + // add a function + _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments))); } /** * Add a native function directly to the extension * @param name Name of the function * @param function The function to add - * @return Function The added function + * @param arguments Optional argument specification */ -Function *Extension::add(const char *name, native_callback_0 function, const std::initializer_list<Argument> &arguments) { return add(new NativeFunction(name, function, arguments)); } -Function *Extension::add(const char *name, native_callback_1 function, const std::initializer_list<Argument> &arguments) { return add(new NativeFunction(name, function, arguments)); } -Function *Extension::add(const char *name, native_callback_2 function, const std::initializer_list<Argument> &arguments) { return add(new NativeFunction(name, function, arguments)); } -Function *Extension::add(const char *name, native_callback_3 function, const std::initializer_list<Argument> &arguments) { return add(new NativeFunction(name, function, arguments)); } +void Extension::add(const char *name, native_callback_2 function, const Arguments &arguments) +{ + // add a function + _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments))); +} + +/** + * Add a native function directly to the extension + * @param name Name of the function + * @param function The function to add + * @param arguments Optional argument specification + */ +void Extension::add(const char *name, native_callback_3 function, const Arguments &arguments) +{ + // add a function + _functions.insert(std::unique_ptr<Function>(new Function(name, function, arguments))); +} /** * Retrieve the module entry @@ -249,29 +272,29 @@ zend_module_entry *Extension::module() if (_entry->functions || _functions.size() == 0) return _entry; // allocate memory for the functions - zend_function_entry *functions = new zend_function_entry[_functions.size() + 1]; + zend_function_entry *entries = new zend_function_entry[_functions.size() + 1]; // keep iterator counter int i = 0; // loop through the functions - for (auto it = begin(_functions); it != _functions.end(); it++) + for (auto &function : _functions) { // retrieve entry - zend_function_entry *entry = &functions[i++]; + zend_function_entry *entry = &entries[i++]; // let the function fill the entry - (*it)->fill(entry); + function->initialize(entry); } // last entry should be set to all zeros - zend_function_entry *last = &functions[i]; + zend_function_entry *last = &entries[i]; // all should be set to zero memset(last, 0, sizeof(zend_function_entry)); // store functions in entry object - _entry->functions = functions; + _entry->functions = entries; // return the entry return _entry; @@ -284,11 +307,7 @@ zend_module_entry *Extension::module() bool Extension::initialize() { // loop through the classes - for (auto iter = _classes.begin(); iter != _classes.end(); iter++) - { - // initialize the class - (*iter)->initialize(); - } + for (auto &iter : _classes) iter->initialize(); // done return true; diff --git a/src/nativefunction.h b/src/function.h index 8b946a3..84d7dcc 100644 --- a/src/nativefunction.h +++ b/src/function.h @@ -1,7 +1,7 @@ /** - * NativeFunction.h + * Function.h * - * The NativeFunction class is an extension of the Function class that + * The Function class is an extension of the Callable class that * forwards the function call directly to a native function in C/C++ * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> @@ -16,7 +16,7 @@ namespace Php { /** * Class definition */ -class NativeFunction : public Function +class Function : public Callable { public: /** @@ -24,15 +24,15 @@ public: * @param name Function name * @param function The native C function */ - NativeFunction(const char *name, native_callback_0 function, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _type(0) { _function.f0 = function; } - NativeFunction(const char *name, native_callback_1 function, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _type(1) { _function.f1 = function; } - NativeFunction(const char *name, native_callback_2 function, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _type(2) { _function.f2 = function; } - NativeFunction(const char *name, native_callback_3 function, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _type(3) { _function.f3 = function; } + Function(const char *name, native_callback_0 function, const Arguments &arguments = {}) : Callable(name, arguments), _type(0) { _function.f0 = function; } + Function(const char *name, native_callback_1 function, const Arguments &arguments = {}) : Callable(name, arguments), _type(1) { _function.f1 = function; } + Function(const char *name, native_callback_2 function, const Arguments &arguments = {}) : Callable(name, arguments), _type(2) { _function.f2 = function; } + Function(const char *name, native_callback_3 function, const Arguments &arguments = {}) : Callable(name, arguments), _type(3) { _function.f3 = function; } /** * Destructor */ - virtual ~NativeFunction() {} + virtual ~Function() {} /** * Method that gets called every time the function is executed diff --git a/src/includes.h b/src/includes.h index 5b97e03..4e6e583 100644 --- a/src/includes.h +++ b/src/includes.h @@ -30,6 +30,7 @@ /** * PHP includes */ +#pragma GCC system_header #include <php.h> #include "zend_exceptions.h" #include "zend_interfaces.h" @@ -54,10 +55,8 @@ #include "../include/hashmember.h" #include "../include/parameters.h" #include "../include/membermodifier.h" -#include "../include/function.h" #include "../include/properties.h" #include "../include/base.h" -#include "../include/method.h" #include "../include/member.h" #include "../include/public.h" #include "../include/protected.h" @@ -65,8 +64,8 @@ #include "../include/const.h" #include "../include/members.h" #include "../include/classmodifier.h" +#include "../include/classbase.h" #include "../include/class.h" -#include "../include/classinfo.h" #include "../include/extension.h" #include "../include/exception.h" #include "../include/init.h" @@ -75,7 +74,9 @@ * Interface files for internal use only */ #include "mixedobject.h" -#include "nativefunction.h" +#include "callable.h" +#include "function.h" +#include "method.h" #include "internalfunction.h" #include "memberinfo.h" #include "nullmember.h" diff --git a/src/member.cpp b/src/member.cpp index 85990cc..e3e7ff2 100644 --- a/src/member.cpp +++ b/src/member.cpp @@ -5,6 +5,9 @@ * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> * @copyright 2013 Copernica BV + * + * + * @todo refactor this class to a property */ #include "includes.h" @@ -13,6 +16,8 @@ */ namespace Php { +#ifdef XXXX + /** * Constructor * @param name Name of the member @@ -218,6 +223,8 @@ void Member::fill(struct _zend_function_entry *entry, const char *classname) _info->fill(entry, classname, _flags); } +#endif + /** * End of namespace */ diff --git a/src/members.cpp b/src/members.cpp index 4ff1b60..1965807 100644 --- a/src/members.cpp +++ b/src/members.cpp @@ -13,76 +13,76 @@ */ namespace Php { -/** - * Destructor - */ -Members::~Members() -{ - // check if there are methods - if (_methods) delete[] _methods; -} - -/** - * Number of methods - * @return integer - */ -int Members::methods() -{ - // result variable - int result = 0; - - // loop through the functions - for (auto it = begin(); it != end(); it++) - { - // check if this is a method - if (it->isMethod()) result++; - } - - // done - return result; -} - -/** - * Get access to the methods - * @return Methods - */ -struct _zend_function_entry *Members::methods(const char *classname) -{ - // already set? - if (_methods) return _methods; - - // the number of methods - int count = methods(); - - // allocate memory for the functions - _methods = new zend_function_entry[count + 1]; - - // keep iterator counter - int i = 0; - - // loop through the functions - for (auto it = begin(); it != end(); it++) - { - // skip if this is not a method - if (!it->isMethod()) continue; - - // retrieve entry - zend_function_entry *entry = &_methods[i++]; - - // let the function fill the entry - it->fill(entry, classname); - } - - // last entry should be set to all zeros - zend_function_entry *last = &_methods[i]; - - // all should be set to zero - memset(last, 0, sizeof(zend_function_entry)); - - // done - return _methods; -} - +///** +// * Destructor +// */ +//Members::~Members() +//{ +// // check if there are methods +// if (_methods) delete[] _methods; +//} +// +///** +// * Number of methods +// * @return integer +// */ +//int Members::methods() +//{ +// // result variable +// int result = 0; +// +// // loop through the functions +// for (auto it = begin(); it != end(); it++) +// { +// // check if this is a method +// if (it->isMethod()) result++; +// } +// +// // done +// return result; +//} +// +///** +// * Get access to the methods +// * @return Methods +// */ +//struct _zend_function_entry *Members::methods(const char *classname) +//{ +// // already set? +// if (_methods) return _methods; +// +// // the number of methods +// int count = methods(); +// +// // allocate memory for the functions +// _methods = new zend_function_entry[count + 1]; +// +// // keep iterator counter +// int i = 0; +// +// // loop through the functions +// for (auto it = begin(); it != end(); it++) +// { +// // skip if this is not a method +// if (!it->isMethod()) continue; +// +// // retrieve entry +// zend_function_entry *entry = &_methods[i++]; +// +// // let the function fill the entry +// it->initialize(classname, entry); +// } +// +// // last entry should be set to all zeros +// zend_function_entry *last = &_methods[i]; +// +// // all should be set to zero +// memset(last, 0, sizeof(zend_function_entry)); +// +// // done +// return _methods; +//} +// /** * End of namespace */ diff --git a/src/method.h b/src/method.h new file mode 100644 index 0000000..cc9f973 --- /dev/null +++ b/src/method.h @@ -0,0 +1,104 @@ +/** + * Method.h + * + * Internal class that represents a native class method, that can be called + * from PHP scripts. + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2014 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class Method : public Callable +{ +public: + /** + * Constructor + * + * @param name Method name + * @param callback Native callback + * @param flags Access flags + * @param args Argument description + */ + Method(const char *name, method_callback_0 callback, int flags, const Arguments &args) : Callable(name, args), _type(0), _flags(flags) { _callback.m0 = callback; } + Method(const char *name, method_callback_1 callback, int flags, const Arguments &args) : Callable(name, args), _type(1), _flags(flags) { _callback.m1 = callback; } + Method(const char *name, method_callback_2 callback, int flags, const Arguments &args) : Callable(name, args), _type(2), _flags(flags) { _callback.m2 = callback; } + Method(const char *name, method_callback_3 callback, int flags, const Arguments &args) : Callable(name, args), _type(3), _flags(flags) { _callback.m3 = callback; } + + /** + * Destructor + * @param type + * @param callback + */ + virtual ~Method() {} + + /** + * Internal method to fill a function entry + * @param zend_function_entry + * @param classname + */ + void initialize(struct _zend_function_entry *entry, const std::string &classname) + { + // call base + Callable::initialize(entry, classname.c_str(), _flags); + } + + /** + * Invoke the method + * @param parameters + * @return Value + */ + virtual Value invoke(Parameters ¶meters) override + { + // the object to call a method on + Base *base = parameters.object(); + + // find out which method to call, and call it + switch (_type) { + case 0: (base->*_callback.m0)(); return Value(); + case 1: (base->*_callback.m1)(parameters); return Value(); + case 2: return (base->*_callback.m2)(); + case 3: return (base->*_callback.m3)(parameters); + default: return Value(); + } + } + + +private: + /** + * Callback type + * @var int + */ + int _type; + + /** + * Access flags (protected, public, abstract, final, private, etc) + * @var int + * @todo use this + */ + int _flags; + + /** + * The actual callback + * @var void* + */ + union { + method_callback_0 m0; + method_callback_1 m1; + method_callback_2 m2; + method_callback_3 m3; + } _callback; +}; + +/** + * End of namespace + */ +} + diff --git a/src/methodbase.cpp b/src/methodbase.cpp new file mode 100644 index 0000000..81ce40a --- /dev/null +++ b/src/methodbase.cpp @@ -0,0 +1,24 @@ +/** + * MethodBase.cpp + * + * Implementation of the MethodBase class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2014 Copernica BV + */ +#include "includes.h" + +/** + * Set up namespace + * + * @todo remove file + */ +namespace Php { + +/** + * End namespace + */ +} + + +
\ No newline at end of file diff --git a/src/methodmember.h b/src/methodmember.h index 709aec9..5d903e9 100644 --- a/src/methodmember.h +++ b/src/methodmember.h @@ -5,6 +5,9 @@ * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> * @copyright 2013 Copernica BV + * + * @todo remove this class + * @todo but do implement this for properties */ /** @@ -12,60 +15,60 @@ */ namespace Php { -/** - * Class definition - */ -class MethodMember : public MemberInfo, public Function -{ -public: - /** - * Constructor - * @param name - * @param method - * @param arguments - */ - MethodMember(const char *name, const _Method &method, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _method(method) {} - - /** - * Destructor - */ - virtual ~MethodMember() {} - - /** - * Is this a method member - * @return bool - */ - virtual bool isMethod() { return true; } - - /** - * Fill a function entry object - * @param entry Function entry - * @param classname Name of the class - * @param method Is this a public entry - */ - virtual void fill(struct _zend_function_entry *entry, const char *classname, MemberModifier flags) override - { - // call function object - Function::fill(entry, classname, flags); - } - - /** - * Method that gets called every time the function is executed - * @param params The parameters that were passed - * @return Variable Return value - */ - virtual Value invoke(Parameters ¶ms) - { - return _method.invoke(params); - } - -private: - /** - * The method pointer - * @var _Method - */ - _Method _method; -}; +///** +// * Class definition +// */ +//class MethodMember : public MemberInfo, public Function +//{ +//public: +// /** +// * Constructor +// * @param name +// * @param method +// * @param arguments +// */ +// MethodMember(const char *name, const _Method &method, const std::initializer_list<Argument> &arguments = {}) : Function(name, arguments), _method(method) {} +// +// /** +// * Destructor +// */ +// virtual ~MethodMember() {} +// +// /** +// * Is this a method member +// * @return bool +// */ +// virtual bool isMethod() { return true; } +// +// /** +// * Fill a function entry object +// * @param entry Function entry +// * @param classname Name of the class +// * @param method Is this a public entry +// */ +// virtual void fill(struct _zend_function_entry *entry, const char *classname, MemberModifier flags) override +// { +// // call function object +// Function::fill(entry, classname, flags); +// } +// +// /** +// * Method that gets called every time the function is executed +// * @param params The parameters that were passed +// * @return Variable Return value +// */ +// virtual Value invoke(Parameters ¶ms) +// { +// return _method.invoke(params); +// } +// +//private: +// /** +// * The method pointer +// * @var _Method +// */ +// _Method _method; +//}; /** * End of namespace diff --git a/src/methods.h b/src/methods.h new file mode 100644 index 0000000..08c129b --- /dev/null +++ b/src/methods.h @@ -0,0 +1,114 @@ +/** + * Methods.h + * + * Class in which all methods are stored. This is a class that is used + * internally by the PHP-CPP library, and that you do not have to use + * as an extension writer. + * + * Essentially, it is std::map that is a littlebit extended with features + * to initialize the methods in the Zend engine + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2014 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class Methods +{ +public: + /** + * Constructor + */ + Methods() {} + + /** + * Destructor + */ + virtual ~Methods() + { + // destruct the entries + if (_entries) delete[] _entries; + } + + /** + * Retrieve an array of zend_function_entry objects that hold the + * properties for each method. This method is called at extension + * startup time to register all methods. + * + * @param classname The class name + * @return zend_function_entry[] + */ + const struct _zend_function_entry *entries(const std::string &classname) + { + // already initialized? + if (_entries) return _entries; + + // allocate memory for the functions + _entries = new zend_function_entry[_methods.size() + 1]; + + // keep iterator counter + int i = 0; + + // loop through the functions + for (auto &method : _methods) + { + // retrieve entry + zend_function_entry *entry = &_entries[i++]; + + // let the function fill the entry + // @todo check flags for the method + method->initialize(entry, classname); + } + + // last entry should be set to all zeros + zend_function_entry *last = &_entries[i]; + + // all should be set to zero + memset(last, 0, sizeof(zend_function_entry)); + + // done + return _entries; + } + + /** + * Add a method + * @param name + * @param method + */ + void add(MethodBase *method) + { + // add the method + _methods.insert(std::shared_ptr<MethodBase>(method)); + } + + +private: + /** + * Pointer to the entries + * @var zend_function_entry[] + */ + struct _zend_function_entry *_entries = nullptr; + + /** + * Map of all methods + * + * A unique_ptr would have been cooler, but that somehow does not compile + * + * @var std::set + */ + std::set<std::shared_ptr<MethodBase>> _methods; + +}; + +/** + * End namespace + */ +} + |