diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2013-08-25 17:40:03 +0200 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2013-08-25 17:40:03 +0200 |
commit | e14055694478d70e58b5fc653b08a9a514bbc455 (patch) | |
tree | ab47d723699a7fe86f47f68c182ab695bf9b3bab /src | |
parent | e838e180f5bbcf19e7235f30311645e942ff92d2 (diff) |
{more work in progress: the function that was defined with c++ now gets calls, but it does not yet call the actual implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/arginfo.h | 97 | ||||
-rw-r--r-- | src/argument.cpp | 60 | ||||
-rw-r--r-- | src/callable.cpp | 87 | ||||
-rw-r--r-- | src/callable.h | 146 | ||||
-rw-r--r-- | src/config.m4 | 4 | ||||
-rw-r--r-- | src/extension.cpp | 11 | ||||
-rw-r--r-- | src/function.cpp | 49 | ||||
-rw-r--r-- | src/functions.h | 80 | ||||
-rw-r--r-- | src/includes.h | 17 |
10 files changed, 549 insertions, 4 deletions
diff --git a/src/Makefile b/src/Makefile index 162e7ee..069024d 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 +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 LD = g++ LD_FLAGS = -Wall -shared -O2 diff --git a/src/arginfo.h b/src/arginfo.h new file mode 100644 index 0000000..8ed00c8 --- /dev/null +++ b/src/arginfo.h @@ -0,0 +1,97 @@ +/** + * ArgInfo.h + * + * Internal class that wraps the Zend information about an argument + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Set up namespace + */ +namespace PhpCpp { + +/** + * Class definition + */ +class ArgInfo +{ +public: + /** + * Constructor if this argument should be an instance of a certain class + * @param name Name of the argument + * @param classname If a specific class is required, the class type + * @param null Are NULL values allowed in stead of an instance? + * @param ref Is this a pass-by-reference argument? + */ + ArgInfo(const std::string &name, const std::string &classname, bool null = true, bool ref = false) : + _name(name), _classname(name), _type(objectType), _null(null), _ref(ref) {} + + /** + * Constructor if this argument can be anything + * @param name Name of the argument + * @param type Type hint + * @param ref Is this a pass-by-reference argument? + */ + ArgInfo(const std::string &name, Type type = nullType, bool ref = false) : + _name(name), _type(type), _null(false), _ref(ref) {} + + /** + * Destructor + */ + virtual ~ArgInfo() {} + + /** + * Fill a zend_arg_info structure + * @param info + */ + void fill(zend_arg_info *info) + { + // fill all members + info->name = _name.c_str(); + info->name_len = _name.size(); + info->class_name = _classname.size() ? _classname.c_str() : NULL; + info->class_name_len = _classname.size(); + info->type_hint = _type; + info->allow_null = _null; + info->pass_by_reference = _ref; + } + +private: + /** + * The argument name + * @var string + */ + std::string _name; + + /** + * The class name + * @var string + */ + std::string _classname; + + /** + * Type of the argument + * @var Type + */ + Type _type; + + /** + * Can this argument be set to NULL? + * @var bool + */ + bool _null; + + /** + * Is this a pass-by-reference argument? + * @var bool + */ + bool _ref; +}; + +/** + * End of namespace + */ +} + diff --git a/src/argument.cpp b/src/argument.cpp new file mode 100644 index 0000000..153da9c --- /dev/null +++ b/src/argument.cpp @@ -0,0 +1,60 @@ +/** + * Argument.cpp + * + * Implementation for the Argument class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace PhpCpp { + +/** + * Constructor if this argument should be an instance of a certain class + * @param name Name of the argument + * @param classname If a specific class is required, the class type + * @param null Are NULL values allowed in stead of an instance? + * @param ref Is this a pass-by-reference argument? + */ +Argument::Argument(const std::string &name, const std::string &classname, bool null, bool ref) +{ + _refcount = new int[1]; + _info = new ArgInfo(name, classname, null, ref); +} + +/** + * Constructor if the argument can be anything + * @param name Name of the argument + * @param type Type hint + * @param ref Is this a pass-by-reference argument? + */ +Argument::Argument(const std::string &name, Type type, bool ref) +{ + _refcount = new int[1]; + _info = new ArgInfo(name, type, ref); +} + +/** + * Clean up the object + */ +void Argument::cleanup() +{ + // one reference less + (*_refcount)--; + + // leap out if still in use + if (*_refcount > 0) return; + + // release memory + delete _refcount; + delete _info; +} + +/** + * End of namespace + */ +} diff --git a/src/callable.cpp b/src/callable.cpp new file mode 100644 index 0000000..1ad4ed2 --- /dev/null +++ b/src/callable.cpp @@ -0,0 +1,87 @@ +/** + * Callable.cpp + * + * Implementation for the Callable class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Namespace + */ +namespace PhpCpp { + +/** + * Function that is called by the Zend engine every time that a function gets called + * @param mixed + */ +void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) +{ + std::cout << "invoke_callable" << std::endl; + +} + +/** + * Fill a function entry + * @param entry + */ +void Callable::fill(zend_function_entry *entry) +{ + // fill the members of the entity + entry->fname = _function.c_str(); + entry->handler = invoke_callable; + entry->arg_info = _argv; + entry->num_args = _argc; + entry->flags = _flags; +} + +/** + * Another attempt to fill internal function info + * @param entry + */ +void Callable::fill(zend_internal_function_info *info) +{ + // fill in all the members, not that the returning by reference is not used + info->_name = _function.c_str(); + info->_name_len = _function.size(); + info->_class_name = _classname.size() ? _classname.c_str() : NULL; + info->required_num_args = _required; + info->_type_hint = _type; + info->return_reference = false; + info->pass_rest_by_reference = false; +} + +/** + * Process the arguments + * @param arguments + */ +void Callable::process(const std::initializer_list<Argument> &arguments) +{ + // store counters + _argc = arguments.size(); + _required = arguments.size(); + + // allocate memory for the arguments, with one extra record to hold information + _argv = new zend_arg_info[_argc + 1]; + + // fill the info + fill((zend_internal_function_info *)_argv); + + // iteration counter + int i = 0; + + // loop through the arguments + for (auto it = begin(arguments); it != arguments.end(); it++) + { + // fill the argument structure + it->internal()->fill(&_argv[++i]); + } +} + +/** + * End of namespace + */ +} + diff --git a/src/callable.h b/src/callable.h new file mode 100644 index 0000000..3903ac7 --- /dev/null +++ b/src/callable.h @@ -0,0 +1,146 @@ +/** + * Callable.h + * + * This is an internal class that is used internally by the Function and Method + * classes, and that wraps the Zend function entry into a CPP object. + * + * This is an internal class, that is not supposed to be used or called from + * outside the PhpCpp library. + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Set up namespace + */ +namespace PhpCpp { + +/** + * Class definition + */ +class Callable +{ +public: + /** + * Constructor + * @param classname Name of the class + * @param function Name of the function or method + * @param type Hint for the return type + * @param arguments The arguments that are passed to the function + * @param flags Optional flags to be passed to the function + */ + Callable(const std::string &classname, const std::string &function, Type type = nullType, const std::initializer_list<Argument> &arguments = {}, int flags = 0) : + _classname(classname), _function(function), _type(type), _flags(flags) + { + // process the arguments + process(arguments); + } + + /** + * Constructor + * @param classname Name of the class + * @param function Name of the function or method + * @param type Hint for the return type + * @param arguments The arguments that are passed to the function + * @param flags Optional flags to be passed to the function + */ + Callable(const std::string &classname, const std::string &function, const std::initializer_list<Argument> &arguments = {}, int flags = 0) : + Callable(classname, function, nullType, arguments, flags) {} + + /** + * Constructor + * @param function Name of the function or method + * @param type Hint for the return type + * @param arguments The arguments that are passed to the function + * @param flags Optional flags to be passed to the function + */ + Callable(const std::string &function, Type type = nullType, const std::initializer_list<Argument> &arguments = {}, int flags = 0) : + Callable("", function, type, arguments, flags) {} + + /** + * Constructor + * @param function Name of the function or method + * @param type Hint for the return type + * @param arguments The arguments that are passed to the function + * @param flags Optional flags to be passed to the function + */ + Callable(const std::string &function, const std::initializer_list<Argument> &arguments = {}, int flags = 0) : + Callable("", function, nullType, arguments, flags) {} + + /** + * Destructor + */ + virtual ~Callable() + { + delete[] _argv; + } + + /** + * Fill a function entry + * @param entry + */ + void fill(zend_function_entry *entry); + + +private: + /** + * Classname + * @var string + */ + std::string _classname; + + /** + * Function name + * @var string + */ + std::string _function; + + /** + * The return type + * @var Type + */ + Type _type; + + /** + * Function flags (like deprecated, abstract, private, etc) + * @var int + */ + int _flags; + + /** + * The number of arguments + * @var int + */ + int _argc; + + /** + * The number of required arguments + * @var int + */ + int _required; + + /** + * The arguments + * @var zend_arg_info[] + */ + zend_arg_info *_argv; + + /** + * Another attempt to fill internal function info + * @param entry + */ + void fill(zend_internal_function_info *info); + + /** + * Process the arguments + * @param arguments + */ + void process(const std::initializer_list<Argument> &arguments); +}; + +/** + * End of namespace + */ +} + diff --git a/src/config.m4 b/src/config.m4 index e69de29..a81d11d 100644 --- a/src/config.m4 +++ b/src/config.m4 @@ -0,0 +1,4 @@ +dnl PHP_REQUIRE_CXX() +dnl PHP_ADD_LIBRARY(stdc++, 1, PHP5CPP_SHARED_LIBADD) +PHP_NEW_EXTENSION(phpcpp, extension.cpp, $ext_shared,,"","yes") + diff --git a/src/extension.cpp b/src/extension.cpp index 94543ef..94b5082 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -22,8 +22,11 @@ static Extension *extension; * @param name Name of the extension * @param version Version number */ -Extension::Extension(const char *name, const char *version) : _name(name), _version(version), _entry(NULL), _request(NULL) +Extension::Extension(const char *name, const char *version, const std::initializer_list<Function> &functions) : _name(name), _version(version) { + // allocate functions + _functions = new Functions(functions); + // store pointer to the one and only extension extension = this; } @@ -33,6 +36,9 @@ Extension::Extension(const char *name, const char *version) : _name(name), _vers */ Extension::~Extension() { + // deallocate functions + delete _functions; + // deallocate entry if (_entry) delete _entry; } @@ -105,7 +111,7 @@ zend_module_entry *Extension::entry() _entry->ini_entry = NULL; // the php.ini record _entry->deps = NULL; // dependencies on other modules _entry->name = _name; // extension name - _entry->functions = NULL; // functions supported by this module + _entry->functions = _functions->internal(); // functions supported by this module _entry->module_startup_func = extension_startup; // startup function for the whole extension _entry->module_shutdown_func = extension_shutdown; // shutdown function for the whole extension _entry->request_startup_func = request_startup; // startup function per request @@ -132,4 +138,3 @@ zend_module_entry *Extension::entry() */ } - diff --git a/src/function.cpp b/src/function.cpp new file mode 100644 index 0000000..54f0717 --- /dev/null +++ b/src/function.cpp @@ -0,0 +1,49 @@ +/** + * Function.cpp + * + * Implementation for the function class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace PhpCpp { + +/** + * Constructor + * @param name Name of the function + * @param arguments The arguments that can be passed to the function + */ +Function::Function(const std::string &name, const std::initializer_list<Argument> &arguments) +{ + // one reference to the callable + _refcount = new int(1); + _callable = new Callable(name, arguments); +} + +/** + * Remove one reference + */ +void Function::cleanup() +{ + // decrease number of references + (*_refcount)--; + + // leap out if there are still other references + if (*_refcount > 0) return; + + // release memory + delete _refcount; + delete _callable; +} + +/** + * End of namespace + */ +} + + diff --git a/src/functions.h b/src/functions.h new file mode 100644 index 0000000..9b28ca2 --- /dev/null +++ b/src/functions.h @@ -0,0 +1,80 @@ +/** + * Functions.h + * + * Internal helper class that parses the functions initializer list, and + * that converts it into a zend_function_entry array. + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Set up namespace + */ +namespace PhpCpp { + +/** + * Class definition + */ +class Functions +{ +public: + /** + * Constructor + * @param functions The functions to parse + */ + Functions(const std::initializer_list<Function> &functions) + { + // allocate the function entries + _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++) + { + // let the callable fill the array + it->internal()->fill(&_entries[i++]); + } + + // 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)); + } + + /** + * Destructor + */ + virtual ~Functions() + { + delete[] _entries; + } + + /** + * Retrieve the internal data + * @return zend_function_entry* + */ + zend_function_entry *internal() + { + return _entries; + } + + +private: + /** + * The internal entries + * @var zend_function_entry* + */ + zend_function_entry *_entries; +}; + +/** + * End of namespace + */ +} + + +
\ No newline at end of file diff --git a/src/includes.h b/src/includes.h index 1decef0..0666dc4 100644 --- a/src/includes.h +++ b/src/includes.h @@ -11,6 +11,12 @@ * Include standard C and C++ libraries */ #include <stdlib.h> +#include <string> +#include <initializer_list> +#include <vector> + +// for debugging +#include <iostream> /** * PHP includes @@ -25,6 +31,17 @@ /** * Include other files from this library */ +#include "../include/type.h" #include "../include/request.h" +#include "../include/argument.h" +#include "../include/variable.h" +#include "../include/function.h" #include "../include/extension.h" +/** + * Interface files for internal use only + */ +#include "callable.h" +#include "arginfo.h" +#include "functions.h" + |