diff options
-rw-r--r-- | include/extension.h | 33 | ||||
-rw-r--r-- | include/function.h | 15 | ||||
-rw-r--r-- | include/functions.h | 71 | ||||
-rw-r--r-- | include/hiddenpointer.h | 264 | ||||
-rw-r--r-- | include/request.h | 2 | ||||
-rw-r--r-- | phpcpp.h | 1 | ||||
-rw-r--r-- | src/arginfo.h | 105 | ||||
-rw-r--r-- | src/callable.cpp | 175 | ||||
-rw-r--r-- | src/callable.h | 157 | ||||
-rw-r--r-- | src/extension.cpp | 67 | ||||
-rw-r--r-- | src/function.cpp | 5 | ||||
-rw-r--r-- | src/includes.h | 4 | ||||
-rw-r--r-- | src/nativefunction.h | 88 | ||||
-rw-r--r-- | tests/simple/simple.cpp | 14 | ||||
-rw-r--r-- | tests/simple/simple.php | 2 | ||||
-rw-r--r-- | tests/simple/test.cpp | 298 |
16 files changed, 325 insertions, 976 deletions
diff --git a/include/extension.h b/include/extension.h index 5dabb8e..ad00593 100644 --- a/include/extension.h +++ b/include/extension.h @@ -11,8 +11,8 @@ * as module in a webserver) many requests are handled by the same extension * instance. * - * This is a template class. You need to pass in the type of an object - * that you use for storing request specific state information. + * This is a template class. You need to pass in the type of an object + * that you use for storing request specific state information. * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> * @copyright 2013 Copernica BV @@ -29,6 +29,20 @@ struct _zend_module_entry; namespace Php { /** + * A couple of predefined native callback functions that can be registered. + * These are functions that optional accept a Request and/or Parameters object, + * and that either return void or a Value object. + */ +typedef void (*native_callback_0)(); +typedef void (*native_callback_1)(Parameters &); +typedef void (*native_callback_2)(Request &); +typedef void (*native_callback_3)(Request &, Parameters &); +typedef Value (*native_callback_4)(); +typedef Value (*native_callback_5)(Parameters &); +typedef Value (*native_callback_6)(Request &); +typedef Value (*native_callback_7)(Request &, Parameters &); + +/** * Class definition */ class Extension @@ -159,6 +173,21 @@ public: Function &add(const char *name, const Function &function); /** + * 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 + */ + Function &add(const char *name, native_callback_0 function); + Function &add(const char *name, native_callback_1 function); + Function &add(const char *name, native_callback_2 function); + Function &add(const char *name, native_callback_3 function); + Function &add(const char *name, native_callback_4 function); + Function &add(const char *name, native_callback_5 function); + Function &add(const char *name, native_callback_6 function); + Function &add(const char *name, native_callback_7 function); + + /** * Retrieve the module entry * * This is the memory address that should be exported by the get_module() diff --git a/include/function.h b/include/function.h index 67d2332..daf8572 100644 --- a/include/function.h +++ b/include/function.h @@ -26,6 +26,18 @@ namespace Php { class Function { public: + +// Function(std::function<Value()> &function); +// Function(std::function<Value(Value&)> &function); +// Function(std::function<Value(Value&,Value&)> &function); +// Function(std::function<Value(Value&,Value&,Value&)> &function); +// Function(std::function<Value(Value&,Value&,Value&,Value&)> &function); +// Function(std::function<void()> &function); +// Function(std::function<void(Value&)> &function); +// Function(std::function<void(Value&,Value&)> &function); +// Function(std::function<void(Value&,Value&,Value&)> &function); +// Function(std::function<void(Value&,Value&,Value&,Value&)> &function); + /** * Constructor * @param min Min number of arguments @@ -87,10 +99,11 @@ public: /** * Method that gets called every time the function is executed + * @param request Request object * @param params The parameters that were passed * @return Variable Return value */ - virtual Value invoke(Parameters ¶ms) + virtual Value invoke(Request &request, Parameters ¶ms) { return 0; } diff --git a/include/functions.h b/include/functions.h deleted file mode 100644 index 69653b4..0000000 --- a/include/functions.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 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 - */ - -/** - * Define structures - */ -struct _zend_function_entry; - -/** - * Set up namespace - */ -namespace Php { - -/** - * Class definition - */ -class Functions -{ -public: - /** - * Constructor - * @param functions The functions to parse - */ - Functions(const std::initializer_list<Function> &functions); - - /** - * Destructor - */ - virtual ~Functions(); - -private: - /** - * Retrieve the internal data - * @return zend_function_entry* - */ - _zend_function_entry *internal() const - { - return _entries; - } - - /** - * The internal entries - * @var zend_function_entry* - */ - _zend_function_entry *_entries; - - /** - * Vector of functions (we need this because the function objects must - * remain in memory, so that we can call the invoke methods on them) - * @var vector - */ - std::vector<Function> _functions; - - /** - * The extension has access to the private elements - */ - friend class Extension; -}; - -/** - * End of namespace - */ -} - diff --git a/include/hiddenpointer.h b/include/hiddenpointer.h index bcb44ba..f29082f 100644 --- a/include/hiddenpointer.h +++ b/include/hiddenpointer.h @@ -1,50 +1,50 @@ /** - * HiddenPointer.h + * HiddenPointer.h * - * Helper class that we use to hide a pointer in a string. We do this - * by creating a string buffer that is a littlebit bigger, and put - * the hidden pointer in front of the name + * Helper class that we use to hide a pointer in a string. We do this + * by creating a string buffer that is a littlebit bigger, and put + * the hidden pointer in front of the name * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV */ /** - * Set up namespace + * Set up namespace */ namespace Php { /** - * Class definition + * Class definition */ template <typename Type> class HiddenPointer { public: - /** - * Constructor to hide the pointer in a buffer - * @param pointer The pointer to hide - * @param text The visible text - * @param size Optional text size - */ - HiddenPointer(Type *pointer, const char *text, int size=-1) - { - // calculate size - if (size < 0) size = strlen(text); + /** + * Constructor to hide the pointer in a buffer + * @param pointer The pointer to hide + * @param text The visible text + * @param size Optional text size + */ + HiddenPointer(Type *pointer, const char *text, int size=-1) + { + // calculate size + if (size < 0) size = strlen(text); - // reserve enough room for the text and the pointer - _data.reserve(size + sizeof(Type *)); - - // store the pointer - _data.assign(std::string((const char *)&pointer, sizeof(Type *))); - - // append the text - _data.append(text, size); - - // store pointers - _pointer = pointer; - _text = _data.c_str() + sizeof(Type *); - } + // reserve enough room for the text and the pointer + _data.reserve(size + sizeof(Type *)); + + // store the pointer + _data.assign(std::string((const char *)&pointer, sizeof(Type *))); + + // append the text + _data.append(text, size); + + // store pointers + _pointer = pointer; + _text = _data.c_str() + sizeof(Type *); + } /** * Hide pointer in buffer @@ -53,114 +53,114 @@ public: */ HiddenPointer(Type *pointer, const std::string &text) : HiddenPointer(pointer, text.c_str(), text.size()) {} - /** - * Constructor to retrieve the object given a buffer - * @param text The visible text - * @param size Size of the text - */ - HiddenPointer(const char *text, int size=-1) - { - // calculate size - if (size < 0) size = strlen(text); - - // the pointer is stored right in front of the name - _pointer = *((Type **)(text - sizeof(Type *))); - _text = text; - } - - /** - * Copy constructor - * @param that - */ - HiddenPointer(const HiddenPointer<Type> &that) : _pointer(that._pointer), _text(that._text), _data(that._data) - { - // if data is filled, the text is located inside the data - if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); - } - - /** - * Destructor - */ - virtual ~HiddenPointer() {} - - /** - * Assignment operator - * @param that - * @return HiddenPointer - */ - HiddenPointer<Type> operator=(const HiddenPointer &that) - { - // skip self assignment - if (&that == this) return *this; - - // copy members - _pointer = that._pointer; - _text = that._text; - _data = that._data; + /** + * Constructor to retrieve the object given a buffer + * @param text The visible text + * @param size Size of the text + */ + HiddenPointer(const char *text, int size=-1) + { + // calculate size + if (size < 0) size = strlen(text); + + // the pointer is stored right in front of the name + _pointer = *((Type **)(text - sizeof(Type *))); + _text = text; + } + + /** + * Copy constructor + * @param that + */ + HiddenPointer(const HiddenPointer<Type> &that) : _pointer(that._pointer), _text(that._text), _data(that._data) + { + // if data is filled, the text is located inside the data + if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); + } + + /** + * Destructor + */ + virtual ~HiddenPointer() {} + + /** + * Assignment operator + * @param that + * @return HiddenPointer + */ + HiddenPointer<Type> operator=(const HiddenPointer &that) + { + // skip self assignment + if (&that == this) return *this; + + // copy members + _pointer = that._pointer; + _text = that._text; + _data = that._data; - // if data is filled, the text is located inside the data - if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); - } - - /** - * Retrieve the pointer - * @return Type* - */ - Type *pointer() - { - return _pointer; - } - - /** - * Retrieve the text - * @return const char * - */ - const char *text() - { - return _text; - } - - /** - * Cast to the pointer - * @return Type* - */ - operator Type* () - { - return _pointer; - } - - /** - * Cast to text - * @return const char * - */ - operator const char * () - { - return _text; - } + // if data is filled, the text is located inside the data + if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); + } + + /** + * Retrieve the pointer + * @return Type* + */ + Type *pointer() + { + return _pointer; + } + + /** + * Retrieve the text + * @return const char * + */ + const char *text() + { + return _text; + } + + /** + * Cast to the pointer + * @return Type* + */ + operator Type* () + { + return _pointer; + } + + /** + * Cast to text + * @return const char * + */ + operator const char * () + { + return _text; + } private: - /** - * The actual pointer - * @var Type* - */ - Type *_pointer; - - /** - * The original text - * @var text - */ - const char *_text; - - /** - * Optional data buffer - * @var string - */ - std::string _data; + /** + * The actual pointer + * @var Type* + */ + Type *_pointer; + + /** + * The original text + * @var text + */ + const char *_text; + + /** + * Optional data buffer + * @var string + */ + std::string _data; }; /** - * End of namespace + * End of namespace */ } diff --git a/include/request.h b/include/request.h index 4183966..d204e85 100644 --- a/include/request.h +++ b/include/request.h @@ -77,7 +77,7 @@ protected: /** * Optional extra data - * @var Type + * @var Type */ Type _data; }; @@ -29,7 +29,6 @@ #include <phpcpp/arguments.h> #include <phpcpp/parameters.h> #include <phpcpp/function.h> -#include <phpcpp/functions.h> #include <phpcpp/extension.h> /** diff --git a/src/arginfo.h b/src/arginfo.h deleted file mode 100644 index 39e0e99..0000000 --- a/src/arginfo.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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 Php { - -/** - * 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 (arrayType or callableType) - * @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) {} - - /** - * Constructor if this argument can be anything - * @param name Name of the argument - * @param ref Is this a pass-by-reference argument? - */ - ArgInfo(const std::string &name, bool ref = false) : - _name(name), _type(nullType), _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/callable.cpp b/src/callable.cpp deleted file mode 100644 index 4db463c..0000000 --- a/src/callable.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/** - * Callable.cpp - * - * Implementation for the Callable class - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV - */ -#include "includes.h" - -/** - * Namespace - */ -namespace Php { - -/** - * Function that is called by the Zend engine every time that a function gets called - * @param ht - * @param return_value - * @param return_value_ptr - * @param this_ptr - * @param return_value_used - * @param tsrm_ls - * @return integer - */ -void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) -{ - // find the function name - const char *function = get_active_function_name(TSRMLS_C); - - // uncover the hidden pointer inside the function name - Callable *callable = HiddenPointer<Callable>(function); - - // call the appropriate object - callable->invoke(INTERNAL_FUNCTION_PARAM_PASSTHRU); -} - -/** - * Fill a function entry - * - * This method is called when the extension is registering itself, when the - * function or method introces himself - * - * @param entry - */ -void Callable::fill(zend_function_entry *entry) -{ - // fill the members of the entity, and hide a pointer to the current object in the name - entry->fname = HiddenPointer<Callable>(this, _name); - entry->handler = invoke_callable; - entry->arg_info = _argv; - entry->num_args = _argc; - entry->flags = _flags; -} - -/** - * Another attempt to fill internal function info - * - * This method is called when the extension is registering itself, when the - * function or method introces himself - * - * @param entry - */ -void Callable::fill(zend_internal_function_info *info) -{ - // fill in all the members, note that return reference is false by default, - // because we do want to return references, inside the name we hide a pointer - // to the current object - info->_name = HiddenPointer<Callable>(this, _name); - info->_name_len = _name.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 - * - * The arguments are called by the user of the PhpCpp library when he - * - * @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]); - } -} - -int do_test(int a, int b) -{ - std::cout << "do_test: " << a << " " << b << std::endl; - - return 77; -} - -/** - * Invoke the method - * @param ht - * @param return_value - * @param return_value_ptr - * @param this_ptr - * @param return_value_used - * @param tsrm_ls - * @return integer - */ -int Callable::invoke(INTERNAL_FUNCTION_PARAMETERS) -{ - std::cout << "args: " << ZEND_NUM_ARGS() << std::endl; - std::cout << "required: " << _required << std::endl; - std::cout << "argc: " << _argc << std::endl; - - // number of arguments should be sufficient // @todo show error message -// if (ZEND_NUM_ARGS() < _required) return FAILURE; - - // and not be too much // @todo show error message -// if (ZEND_NUM_ARGS() > _argc) return FAILURE; - - // number of arguments on the stack - int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1); - -// // loop through the arguments -// Arguments args(ZEND_NUM_ARGS()); -// -// for (auto iter = args.begin(); iter != args.end(); iter++) -// { -// Value val = *iter; -// -// val = 1234; -// } -// -// int result = do_test(args[1], args[2]); -// - Value ret(return_value, true); - - std::cout << "set property 1" << std::endl; - -// ret["b"] = "hallo"; - - ret["x"]["c"]["d"] = "test 123"; - - std::cout << "done setting properties" << std::endl; - - -// -// // done - return SUCCESS; -} - - - - -/** - * End of namespace - */ -} - diff --git a/src/callable.h b/src/callable.h deleted file mode 100644 index 293e3aa..0000000 --- a/src/callable.h +++ /dev/null @@ -1,157 +0,0 @@ -/** - * 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 Php { - -/** - * 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), _name(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); - - /** - * Invoke the method - * @param ht - * @param return_value - * @param return_value_ptr - * @param this_ptr - * @param return_value_used - * @param tsrm_ls - * @return integer - */ - int invoke(INTERNAL_FUNCTION_PARAMETERS); - -private: - /** - * Classname (in case of a member function) - * @var string - */ - std::string _classname; - - /** - * The function name - * @var string - */ - std::string _name; - - /** - * 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/extension.cpp b/src/extension.cpp index 2d9ef9f..1fd4b65 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -23,13 +23,13 @@ namespace Php { * The way how PHP C API deals with "global" variables is stupid. * * This is supposed to turn into a structure that is going to be - * instantiated for each parallel running request, and for which the - * PHP engine allocates a certain amount of memory, and a magic + * instantiated for each parallel running request, and for which the + * PHP engine allocates a certain amount of memory, and a magic * pointer that is passed and should be forwarded to every thinkable - * PHP function. + * PHP function. * - * We don't like this architecture. We have our own request object - * that makes much more sense, and that we use. However, we need + * We don't like this architecture. We have our own request object + * that makes much more sense, and that we use. However, we need * to assign this object somewhere, so that's what we do in this * one and only global variable */ @@ -39,7 +39,7 @@ ZEND_END_MODULE_GLOBALS(phpcpp) /** * And now we're going to define a macro. This also is a ridiculous - * architecture from PHP to get access to a variable from the + * architecture from PHP to get access to a variable from the * structure above. */ #ifdef ZTS @@ -61,7 +61,7 @@ static ZEND_DECLARE_MODULE_GLOBALS(phpcpp) * Function that must be defined to initialize the "globals" * We do not have to initialize anything, but PHP needs to call this * method (crazy) - * @param globals + * @param globals */ static void php_phpcpp_init_globals(zend_phpcpp_globals *globals) {} @@ -69,17 +69,17 @@ static void php_phpcpp_init_globals(zend_phpcpp_globals *globals) {} /** * Helper method to get back the current extension object - * @return Extension + * @return Extension */ static Extension *get_extension() { - // retrieve the extension or module name (because PHP of course does - // not pass such extremely useful information as they've no clue how - // to make a decent API - zend_module_entry *module = EG(current_module); + // retrieve the extension or module name (because PHP of course does + // not pass such extremely useful information as they've no clue how + // to make a decent API + zend_module_entry *module = EG(current_module); - // the pointer to the extension is hidden in front of the name - return HiddenPointer<Extension>(module->name); + // the pointer to the extension is hidden in front of the name + return HiddenPointer<Extension>(module->name); } /** @@ -90,12 +90,12 @@ static Extension *get_extension() */ static int extension_startup(INIT_FUNC_ARGS) { - - - - // initialize and allocate the "global" variables -// ZEND_INIT_MODULE_GLOBALS(hello, php_phpcpp_init_globals, NULL); - + + + + // initialize and allocate the "global" variables +// ZEND_INIT_MODULE_GLOBALS(hello, php_phpcpp_init_globals, NULL); + // initialize the extension return BOOL2SUCCESS(get_extension()->initialize()); } @@ -108,6 +108,11 @@ static int extension_startup(INIT_FUNC_ARGS) */ static int extension_shutdown(SHUTDOWN_FUNC_ARGS) { + std::cout << "extension_shutdown" << std::endl; + + // @todo the get_extension() call crashes, we need a different way to find the extension + return 0; + // finalize the extension return BOOL2SUCCESS(get_extension()->finalize()); } @@ -132,6 +137,11 @@ static int request_startup(INIT_FUNC_ARGS) */ static int request_shutdown(INIT_FUNC_ARGS) { + std::cout << "request_shutdown" << std::endl; + + // @todo the get_extension() call crashes, we need a different way to find the extension + return 0; + // end the request return BOOL2SUCCESS(get_extension()->endRequest()); } @@ -190,6 +200,8 @@ Extension::Extension(const char *name, const char *version) : _ptr(this, name) */ Extension::~Extension() { + std::cout << "destruct extension" << std::endl; + // deallocate functions if (_entry->functions) delete[] _entry->functions; @@ -210,6 +222,21 @@ Function &Extension::add(const char *name, const Function &function) } /** + * 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 + */ +Function &Extension::add(const char *name, native_callback_0 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_1 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_2 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_3 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_4 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_5 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_6 function) { add(name, NativeFunction(function)); } +Function &Extension::add(const char *name, native_callback_7 function) { add(name, NativeFunction(function)); } + +/** * Retrieve the module entry * @return zend_module_entry */ diff --git a/src/function.cpp b/src/function.cpp index 8612cf1..13d4d27 100644 --- a/src/function.cpp +++ b/src/function.cpp @@ -37,8 +37,11 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS) // construct parameters Parameters params(ZEND_NUM_ARGS()); + // @todo get the appropriate request (or environment) + Request request(NULL); + // call the appropriate object - ret = function->invoke(params); + ret = function->invoke(request, params); } /** diff --git a/src/includes.h b/src/includes.h index 1a464e0..8d83752 100644 --- a/src/includes.h +++ b/src/includes.h @@ -42,11 +42,9 @@ #include "../include/arguments.h" #include "../include/parameters.h" #include "../include/function.h" -#include "../include/functions.h" #include "../include/extension.h" /** * Interface files for internal use only */ -#include "callable.h" -#include "arginfo.h" +#include "nativefunction.h" diff --git a/src/nativefunction.h b/src/nativefunction.h new file mode 100644 index 0000000..7f36608 --- /dev/null +++ b/src/nativefunction.h @@ -0,0 +1,88 @@ +/** + * NativeFunction.h + * + * The NativeFunction class is an extension of the Function class that + * forwards the function call directly to a native function in C/C++ + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2013 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class NativeFunction : public Function +{ +public: + /** + * Constructor + * @param function + */ + NativeFunction(native_callback_0 function) : _type(0) { _function.f0 = function; } + NativeFunction(native_callback_1 function) : _type(1) { _function.f1 = function; } + NativeFunction(native_callback_2 function) : _type(2) { _function.f2 = function; } + NativeFunction(native_callback_3 function) : _type(3) { _function.f3 = function; } + NativeFunction(native_callback_4 function) : _type(4) { _function.f4 = function; } + NativeFunction(native_callback_5 function) : _type(5) { _function.f5 = function; } + NativeFunction(native_callback_6 function) : _type(6) { _function.f6 = function; } + NativeFunction(native_callback_7 function) : _type(7) { _function.f7 = function; } + + /** + * Destructor + */ + virtual ~NativeFunction() {} + + /** + * Method that gets called every time the function is executed + * @param request Request environment + * @param params The parameters that were passed + * @return Variable Return value + */ + virtual Value invoke(Request &request, Parameters ¶ms) + { + switch (_type) { + case 0: _function.f0(); return Value(); + case 1: _function.f1(params); return Value(); + case 2: _function.f2(request); return Value(); + case 3: _function.f3(request, params); return Value(); + case 4: return _function.f4(); + case 5: return _function.f5(params); + case 6: return _function.f6(request); + case 7: return _function.f7(request, params); + default: return Value(); + } + } + +private: + /** + * Union of supported callbacks + * One of the callbacks will be set + */ + union { + native_callback_0 f0; + native_callback_1 f1; + native_callback_2 f2; + native_callback_3 f3; + native_callback_4 f4; + native_callback_5 f5; + native_callback_6 f6; + native_callback_7 f7; + } _function; + + /** + * The callback that is set + * @var integer + */ + int _type; +}; + +/** + * End of namespace + */ +} + diff --git a/tests/simple/simple.cpp b/tests/simple/simple.cpp index a33b220..311ce4c 100644 --- a/tests/simple/simple.cpp +++ b/tests/simple/simple.cpp @@ -15,14 +15,12 @@ */ using namespace std; -static int my_plus(int a, int b) +static Php::Value my_plus(Php::Parameters ¶ms) { - return a + b; -} - -static std::string my_concat(std::string &a, std::string &b) -{ - return a + b; + string p1 = params[0]; + string p2 = params[1]; + + return p1 + p2; } class MyCustomFunction : public Php::Function @@ -45,7 +43,7 @@ extern "C" cout << "b" << endl; // define the functions -// extension.add("my_plus", my_plus); + extension.add("my_plus", my_plus); // extension.add("my_concat", my_concat); extension.add("my_custom", MyCustomFunction()); diff --git a/tests/simple/simple.php b/tests/simple/simple.php index bdf2b74..fc552fd 100644 --- a/tests/simple/simple.php +++ b/tests/simple/simple.php @@ -10,7 +10,7 @@ class XXX $myvar = "hoi"; -$result = hallo($myvar, 1, 2, 3, "blabla", new XXX()); +$result = my_plus($myvar, 1, 2, 3, "blabla", new XXX()); echo("myvar = $myvar\n"); diff --git a/tests/simple/test.cpp b/tests/simple/test.cpp deleted file mode 100644 index dbae91e..0000000 --- a/tests/simple/test.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include <iostream> -#include <functional> -#include <sstream> -#include <vector> -#include <map> -#include <stdlib.h> - -using namespace std; - -/** - * Example function that adds numbers - * @param a A number - * @param b A different number - * @return Sum of both parameters - */ -int my_plus(int a, int b) -{ - cout << "my_plus(" << a << ", " << b << ")" << endl; - - return a + b; -} - -/** - * Another example function that concatenates strings - * @param a A text - * @param b A different text - * @return Concattenation - */ -const string my_concat(const string &a, const string &b) -{ - cout << "my_concat(" << a << ", " << b << ")" << endl; - - return a + b; -} - -/** - * Value class that can automatically convert objects between many - * different types - */ -class Value -{ -private: - /** - * Internal representation - * @var _value - */ - string _value; - -public: - /** - * Constructor based on string - * @param text - */ - Value(const string &text) : _value(text) {} - - /** - * Constructor based on string - * @param text - */ - Value(const char *text) : _value(text) {} - - /** - * Constructor based on int - * @param integer - */ - Value(int value) - { - ostringstream s; - s << value; - _value = s.str(); - } - - /** - * Destructor - */ - virtual ~Value() {} - - /** - * Cast to integer - * @return Numeric representation - */ - operator int () - { - return atoi(_value.c_str()); - } - - /** - * Cast to string - * @return String representation - */ - operator const string& () - { - return _value; - } -}; - -/** - * Simple wrapper around a function - */ -class Function -{ -private: - /** - * The actual function - * - * Note: there must be a much smarter way to achieve the same thing, - * we just want to have a single member that holds the function - * - * @var _function - */ - union F { - // union members - function<Value()> r0; - function<Value(Value&)> r1; - function<Value(Value&,Value&)> r2; - function<void()> v0; - function<void(Value&)> v1; - function<void(Value&,Value&)> v2; - - // constructors - F() {} - F(function<Value()> &f) { r0 = f; } - F(function<Value(Value&)> &f) { r1 = f; } - F(function<Value(Value&,Value&)> &f) { r2 = f; } - F(function<void()> &f) { v0 = f; } - F(function<void(Value&)> &f) { v1 = f; } - F(function<void(Value&,Value&)> &f) { v2 = f; } - - // destructor - ~F(); - - // assignment operator -// F &operator=(function<Value()> &f) { r0 = f; return *this; } -// F &operator=(function<Value(Value&)> &f) { r1 = f; return *this; } -// F &operator=(function<Value(Value&,Value&)> &f) { r2 = f; return *this; } - - } _function; - - /** - * Is the object in a valid state - * @var bool - */ - bool _valid; - - /** - * The number of arguments that the function required - * @var _argc - */ - int _argc; - - /** - * Does the function return something? - * @var _return; - */ - bool _return; - -public: - /** - * Contructor - * @param f - */ - Function(function<Value()> &f) : _function(f) - { - _argc = 0; - _return = true; - _valid = true; - } - - /** - * Contructor - * @param f - */ - Function(function<Value(Value&)> &f) : _function(f) - { - _argc = 1; - _return = true; - } - - /** - * Contructor - * @param f - */ - Function(function<Value(Value&,Value&)> &f) : _function(f) - { - _argc = 2; - _return = true; - } - - /** - * Move constructor - * @param f - */ - Function(const Function &&f) - { - // copy params - _argc = f._argc; - _return = f._return; - - switch (_argc) { - case 0: _function.r0 = f._function.r0; break; - case 1: _function.r1 = f._function.r1; break; - case 2: _function.r2 = f._function.r2; break; - } - } - - /** - * Destructor - */ - virtual ~Function() {} - - /** - * Operator to call the function - * @param args - */ - void operator()(vector<Value> args) - { - switch (_argc) { - case 0: _function.r0(); - case 1: _function.r1(args[0]); - case 2: _function.r2(args[0], args[1]); - } - } -}; - -/** - * Class that stores pointers to functions - */ -class Functions -{ -private: - /** - * Map of functions - * @var map - */ - map<string,Function> _functions; - -public: - /** - * Constructor - */ - Functions() {} - - /** - * Destructor - */ - virtual ~Functions() {} - - /** - * Add a function - * @param name The function name - * @param func The function to call - */ - void add(const string &name, function<Value(Value&,Value&)> f) - { - _functions.insert(pair<string,Function>(name, Function(f))); - } - - /** - * Call the functions - * @param args - */ - Value operator()(vector<Value> args) - { - for (auto it = _functions.begin(); it != _functions.end(); it++) - { - it->second(args); - } - - return Value(123); - } - -}; - -/** - * Main function - * @param argc - * @param argv - */ -int main(int argc, char *argv[]) -{ - // create a vector of arguments - vector<Value> arguments; - - // fill the arguments - for (int i=1; i<argc-1; i++) arguments.push_back(argv[i]); - - // now register all functions - Functions functions; - functions.add("plus", my_plus); - functions.add("concat", my_concat); - - // call all functions - functions(arguments); - - // done - return 0; -} - |