summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-08 16:26:11 -0700
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-09-08 16:26:11 -0700
commitdf2520e4b2c87e2302ee4c6cec1e672091efebfb (patch)
treef3bcd4fa7c4d0c6ee601268ceca4d6841ed90d0d
parenteb86ac350756afeffa0e2db8be87876d35bc40a8 (diff)
Refactoring function class, and making it even more easy to directly enable native C functions in PHP
-rw-r--r--include/argument.h127
-rw-r--r--include/arguments.h69
-rw-r--r--include/extension.h45
-rw-r--r--include/function.h108
-rw-r--r--include/functions.h2
-rw-r--r--include/hiddenpointer.h (renamed from src/hiddenpointer.h)2
-rw-r--r--include/member.h2
-rw-r--r--include/parameters.h38
-rw-r--r--include/request.h2
-rw-r--r--include/type.h2
-rw-r--r--include/value.h2
-rw-r--r--phpcpp.h4
-rw-r--r--src/arginfo.h2
-rw-r--r--src/argument.cpp74
-rw-r--r--src/arguments.cpp46
-rw-r--r--src/callable.cpp4
-rw-r--r--src/callable.h2
-rw-r--r--src/extension.cpp130
-rw-r--r--src/function.cpp76
-rw-r--r--src/functions.cpp54
-rw-r--r--src/includes.h5
-rw-r--r--src/parameters.cpp39
-rw-r--r--src/value.cpp2
-rw-r--r--tests/simple/simple.cpp28
24 files changed, 593 insertions, 272 deletions
diff --git a/include/argument.h b/include/argument.h
index 5c0c23f..7a95f7d 100644
--- a/include/argument.h
+++ b/include/argument.h
@@ -9,14 +9,14 @@
*/
/**
- * Set up namespace
+ * Forward declaration
*/
-namespace PhpCpp {
+struct _zend_arg_info;
/**
- * Forward definitions
+ * Set up namespace
*/
-class ArgInfo;
+namespace Php {
/**
* Class definition
@@ -25,105 +25,72 @@ class Argument
{
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?
+ * Prevent copying
+ * @param argument
*/
- Argument(const std::string &name, const std::string &classname, bool null = true, bool ref = false);
-
+ Argument(const Argument &argument) = delete;
+
/**
- * Constructor if the argument can be anything
- * Note that only arrayType and callableType are supported type-hints
- * @param name Name of the argument
- * @param type Type hint (arrayType or callableType)
- * @param ref Is this a pass-by-reference argument?
+ * Move constructor
+ * @param argument
*/
- Argument(const std::string &name, Type type = nullType, bool ref = false);
-
+ Argument(Argument &&argument);
+
/**
- * Constructor if the argument can be anything
- * @param name Name of the argument
- * @param ref Is this a pass-by-reference argument?
+ * Destructor
*/
- Argument(const std::string &name, bool ref = false);
+ virtual ~Argument() {};
/**
- * Copy constructor
- * @param argument The argument to copy
+ * Change the name
+ * @param name
+ * @return Argument
*/
- Argument(const Argument &argument)
- {
- // copy members
- _refcount = argument._refcount;
- _info = argument._info;
-
- // increase references
- (*_refcount)++;
- }
+ Argument &name(const char *name);
/**
- * Destructor
+ * Change the type
+ * @param type
+ * @return Argument
*/
- virtual ~Argument()
- {
- // cleanup current object
- cleanup();
- }
-
+ Argument &type(Type type = nullType);
+
/**
- * Copy operator
- * @param argument The argument to copy
+ * Require the parameter to be a certain class
+ * @param name Name of the class
+ * @param null Are null values allowed?
* @return Argument
*/
- Argument &operator=(const Argument &argument)
- {
- // skip self assignment
- if (this == &argument) return *this;
-
- // clean up current object
- cleanup();
-
- // copy members
- _refcount = argument._refcount;
- _info = argument._info;
-
- // increase references
- (*_refcount)++;
-
- // done
- return *this;
- }
+ Argument &object(const char *classname, bool null = true);
/**
- * Retrieve argument info
- * @return ArgInfo
- * @internal
+ * Is this a by-ref argument?
+ * @param bool Mark as by-ref variable
+ * @return Argument
*/
- ArgInfo *internal() const
- {
- return _info;
- }
-
-private:
+ Argument &byref(bool value = true);
+
/**
- * Number of references
- * @var int
+ * Prevent copy
+ * @param argument The argument to copy
+ * @return Argument
*/
- int *_refcount;
-
+ Argument &operator=(const Argument &argument) = delete;
+
+protected:
/**
- * Pointer to the implementation
- * @var ArgInfo
+ * Protected constructor, to prevent that users can instantiate the
+ * argument object themselves
+ * @param info
*/
- ArgInfo *_info;
-
+ Argument(struct _zend_arg_info *info) : _info(info) {}
+
+private:
/**
- * Remove one reference from the object
+ * The argument info
+ * @var zend_arg_info
*/
- void cleanup();
-
+ struct _zend_arg_info *_info;
};
/**
diff --git a/include/arguments.h b/include/arguments.h
index 65476c3..e57903f 100644
--- a/include/arguments.h
+++ b/include/arguments.h
@@ -9,26 +9,85 @@
*/
/**
+ * Forward declaration
+ */
+struct _zend_arg_info;
+
+/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
*/
-class Arguments : public std::vector<Value>
+class Arguments
{
public:
/**
* Constructor
- * @param argc The number of arguments
+ * @param min The min number of arguments
+ * @param max The max number of arguments
+ */
+ Arguments(int min, int max);
+
+ /**
+ * No copy or move operations
+ * @param arguments
*/
- Arguments(int argc);
+ Arguments(const Arguments &arguments) = delete;
+ Arguments(Arguments &&arguments) = delete;
/**
* Destructor
*/
- virtual ~Arguments() {}
+ virtual ~Arguments();
+
+ /**
+ * Number of arguments
+ * @return int
+ */
+ int argc()
+ {
+ return _max;
+ }
+
+ /**
+ * Number of required arguments
+ * @return int
+ */
+ int required()
+ {
+ return _min;
+ }
+
+ /**
+ * Get access to internal data
+ * @return zend_arg_info*
+ */
+ struct _zend_arg_info *internal()
+ {
+ return _argv;
+ }
+
+private:
+ /**
+ * Min number of arguments
+ * @var integer
+ */
+ int _min;
+
+ /**
+ * Max number of arguments
+ * @var integer
+ */
+ int _max;
+
+ /**
+ * The arguments
+ * @var zend_arg_info[]
+ */
+ struct _zend_arg_info *_argv;
};
diff --git a/include/extension.h b/include/extension.h
index 1962fd7..5dabb8e 100644
--- a/include/extension.h
+++ b/include/extension.h
@@ -26,7 +26,7 @@ struct _zend_module_entry;
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
@@ -40,7 +40,7 @@ public:
* @param version Extension version string
* @param functions The functions that are defined
*/
- Extension(const char *name, const char *version, const Functions &functions);
+ Extension(const char *name = NULL, const char *version = NULL);
/**
* No copy'ing and no moving
@@ -51,7 +51,7 @@ public:
/**
* Destructor
*/
- virtual ~Extension() { delete _entry; }
+ virtual ~Extension();
/**
* Initialize the extension.
@@ -117,6 +117,8 @@ public:
//
// // and initialize it
// return _request->initialize();
+
+ return true;
}
/**
@@ -140,10 +142,47 @@ public:
//
// // done
// return result;
+
+ return true;
}
+ /**
+ * Add a function to the extension
+ *
+ * It is only possible to create functions during the initialization of
+ * the library, before the Extension::module() method is called.
+ *
+ * @param name Name of the function
+ * @param function The function to add
+ * @return Function The added function
+ */
+ Function &add(const char *name, const Function &function);
+
+ /**
+ * Retrieve the module entry
+ *
+ * This is the memory address that should be exported by the get_module()
+ * function.
+ *
+ * @return _zend_module_entry
+ */
+ _zend_module_entry *module();
+
+
private:
/**
+ * Map of function objects defined in the library
+ * @var map
+ */
+ std::map<const char *,Function> _functions;
+
+ /**
+ * Hidden pointer to self
+ * @var HiddenPointer
+ */
+ HiddenPointer<Extension> _ptr;
+
+ /**
* The information that is passed to the Zend engine
*
* Although it would be slightly faster to not make this a pointer, this
diff --git a/include/function.h b/include/function.h
index ef185ce..67d2332 100644
--- a/include/function.h
+++ b/include/function.h
@@ -8,16 +8,17 @@
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
* @copyright 2013 Copernica BV
*/
-
-/**
- * Set up namespace
- */
-namespace PhpCpp {
/**
* Forward definitions
*/
-class Callable;
+struct _zend_function_entry;
+struct _zend_internal_function_info;
+
+/**
+ * Set up namespace
+ */
+namespace Php {
/**
* Class definition
@@ -27,22 +28,25 @@ class Function
public:
/**
* Constructor
- * @param name Name of the function
- * @param arguments The arguments that can be passed to the function
- */
- Function(const std::string &name, const std::initializer_list<Argument> &arguments);
-
- /**
- * Constructor
- * @param name Name of the function
+ * @param min Min number of arguments
+ * @param max Max number of arguments
*/
- Function(const char *name) : Function(name, {}) {}
+ Function(int min = 0, int max = 0)
+ {
+ // construct the arguments
+ _arguments = std::shared_ptr<Arguments>(new Arguments(min, max));
+ }
/**
* No copy constructor
* @param function The other function
*/
- Function(const Function &function) = delete;
+ Function(const Function &function)
+ {
+ // copy members
+ _arguments = function._arguments;
+ _type = function._type;
+ }
/**
* Move constructor
@@ -50,46 +54,80 @@ public:
*/
Function(Function &&function)
{
- _callable = function._callable;
- function._callable = nullptr;
+ // copy arguments
+ _arguments = function._arguments;
+ _type = function._type;
+
+ // no longer need the other arguments
+ function._arguments.reset();
}
/**
* Destructor
*/
- virtual ~Function();
+ virtual ~Function() {}
/**
- * No assignment operator
+ * Assignment operator
* @param function The other function
* @return Function
*/
- Function &operator=(const Function &function) {}
+ Function &operator=(const Function &function)
+ {
+ // skip self reference
+ if (this == &function) return *this;
+
+ // copy members
+ _arguments = function._arguments;
+ _type = function._type;
+
+ // done
+ return *this;
+ }
/**
* Method that gets called every time the function is executed
- * @param request The request during which the call was made
- * @param arguments The actual arguments that were passed
+ * @param params The parameters that were passed
* @return Variable Return value
*/
- virtual Value invoke(const Request *request, const std::initializer_list<Value> &arguments);
-
- /**
- * Get access to the internal object
- * @return Callable
- * @internal
- */
- Callable *internal() const
+ virtual Value invoke(Parameters &params)
{
- return _callable;
+ return 0;
}
protected:
/**
- * Pointer to the callable object
- * @var smart_ptr
+ * Suggestion for the return type
+ * @var Type
+ */
+ Type _type = nullType;
+
+ /**
+ * Pointer to the arguments
+ * @var shared_ptr
*/
- Callable *_callable;
+ std::shared_ptr<Arguments> _arguments;
+
+private:
+ /**
+ * Fill a function entry
+ * @param name Name of the function
+ * @param entry Entry to be filled
+ */
+ void fill(const char *name, struct _zend_function_entry *entry);
+
+ /**
+ * Fill function info
+ * @param name Name of the function
+ * @param info Info object to be filled
+ */
+ void fill(const char *name, struct _zend_internal_function_info *info);
+
+ /**
+ * Extension has access to the private members
+ */
+ friend class Extension;
+
};
/**
diff --git a/include/functions.h b/include/functions.h
index fc44f1c..69653b4 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -16,7 +16,7 @@ struct _zend_function_entry;
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
diff --git a/src/hiddenpointer.h b/include/hiddenpointer.h
index 8e03eb2..bcb44ba 100644
--- a/src/hiddenpointer.h
+++ b/include/hiddenpointer.h
@@ -12,7 +12,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
diff --git a/include/member.h b/include/member.h
index d56b495..5166535 100644
--- a/include/member.h
+++ b/include/member.h
@@ -16,7 +16,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Forward definitions
diff --git a/include/parameters.h b/include/parameters.h
new file mode 100644
index 0000000..138d973
--- /dev/null
+++ b/include/parameters.h
@@ -0,0 +1,38 @@
+/**
+ * Parameters.h
+ *
+ * Wrapper around parameters that are passed to a
+
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2013 Copernica BV
+ */
+
+/**
+ * Namespace
+ */
+namespace Php {
+
+/**
+ * Class definition
+ */
+class Parameters : public std::vector<Value>
+{
+public:
+ /**
+ * Constructor
+ * @param argc Number of arguments
+ * @param tsrm_ls
+ */
+ Parameters(int argc);// TSRMLS_DC);
+
+ /**
+ * Destructor
+ */
+ virtual ~Parameters() {}
+};
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/include/request.h b/include/request.h
index f37a449..4183966 100644
--- a/include/request.h
+++ b/include/request.h
@@ -17,7 +17,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Forward definitions
diff --git a/include/type.h b/include/type.h
index 200d658..04e488b 100644
--- a/include/type.h
+++ b/include/type.h
@@ -11,7 +11,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Supported types for variables
diff --git a/include/value.h b/include/value.h
index 2cc9029..64f92df 100644
--- a/include/value.h
+++ b/include/value.h
@@ -26,7 +26,7 @@ struct _zval_struct;
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Forward definitions
diff --git a/phpcpp.h b/phpcpp.h
index 35b790a..55234e9 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -14,16 +14,20 @@
#include <string>
#include <initializer_list>
#include <vector>
+#include <map>
+#include <memory>
/**
* Include all headers files that are related to this library
*/
+#include <phpcpp/hiddenpointer.h>
#include <phpcpp/type.h>
#include <phpcpp/request.h>
#include <phpcpp/argument.h>
#include <phpcpp/value.h>
#include <phpcpp/member.h>
#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
index 0080667..39e0e99 100644
--- a/src/arginfo.h
+++ b/src/arginfo.h
@@ -10,7 +10,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
diff --git a/src/argument.cpp b/src/argument.cpp
index 627ee05..387151a 100644
--- a/src/argument.cpp
+++ b/src/argument.cpp
@@ -11,59 +11,65 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
- * 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?
+ * Move constructor
+ * @param argument
*/
-Argument::Argument(const std::string &name, const std::string &classname, bool null, bool ref)
+Argument::Argument(Argument &&argument)
{
- _refcount = new int(1);
- _info = new ArgInfo(name, classname, null, ref);
+ // copy data
+ _info = argument._info;
}
/**
- * Constructor if the argument can be anything
- * Note that only arrayType and callableType are supported type-hints
- * @param name Name of the argument
- * @param type Type hint (arrayType or callableType)
- * @param ref Is this a pass-by-reference argument?
+ * Change the name
+ * @param name
+ * @return Argument
*/
-Argument::Argument(const std::string &name, Type type, bool ref)
+Argument &Argument::name(const char *name)
{
- _refcount = new int(1);
- _info = new ArgInfo(name, type, ref);
+ _info->name = name;
+ _info->name_len = strlen(name);
+ return *this;
}
/**
- * Constructor if the argument can be anything
- * @param name Name of the argument
- * @param ref Is this a pass-by-reference argument?
+ * Change the type
+ * @param type
+ * @return Argument
*/
-Argument::Argument(const std::string &name, bool ref)
+Argument &Argument::type(Type type)
{
- _refcount = new int(1);
- _info = new ArgInfo(name, ref);
+ _info->type_hint = type;
+ return *this;
}
/**
- * Clean up the object
+ * Require the parameter to be a certain class
+ * @param name Name of the class
+ * @param null Are null values allowed?
+ * @return Argument
*/
-void Argument::cleanup()
+Argument &Argument::object(const char *classname, bool null)
{
- // one reference less
- (*_refcount)--;
-
- // leap out if still in use
- if (*_refcount > 0) return;
-
- // release memory
- delete _refcount;
- delete _info;
+ _info->type_hint = objectType;
+ _info->class_name = classname;
+ _info->class_name_len = strlen(classname);
+ _info->allow_null = null;
+ return *this;
+}
+
+/**
+ * Is this a by-ref argument?
+ * @param bool Mark as by-ref variable
+ * @return Argument
+ */
+Argument &Argument::byref(bool value)
+{
+ _info->pass_by_reference = value;
+ return *this;
}
/**
diff --git a/src/arguments.cpp b/src/arguments.cpp
index e5e7ae5..53f030b 100644
--- a/src/arguments.cpp
+++ b/src/arguments.cpp
@@ -11,13 +11,55 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
+
+/**
+ * Constructor
+ * @param min The min number of arguments
+ * @param max The max number of arguments
+ */
+Arguments::Arguments(int min, int max)
+{
+ // copy arguments
+ _min = min;
+ _max = max;
+ // max should be appropriate
+ if (_max < _min) _max = _min;
+
+ // allocate memory for the arguments, with one extra record to hold information
+ _argv = new zend_arg_info[_max + 1];
+
+ // initialize the arguments
+ for (int i=1; i<_max+1; i++)
+ {
+ // initialize the argument
+ _argv[i].name = NULL;
+ _argv[i].name_len = 0;
+ _argv[i].class_name = NULL;
+ _argv[i].class_name_len = 0;
+ _argv[i].type_hint = nullType;
+ _argv[i].allow_null = false;
+ _argv[i].pass_by_reference = false;
+ }
+}
+
+/**
+ * Destructor
+ */
+Arguments::~Arguments()
+{
+ // deallocate arguments
+ delete[] _argv;
+}
+
/**
* Constructor
* @param argc Number of arguments
* @param tsrm_ls
*/
+/*
+
Arguments::Arguments(int argc TSRMLS_DC)
{
// reserve plenty of space
@@ -33,6 +75,8 @@ Arguments::Arguments(int argc TSRMLS_DC)
push_back(Value(*arg));
}
}
+*
+*/
/**
* End of namespace
diff --git a/src/callable.cpp b/src/callable.cpp
index 69ef148..4db463c 100644
--- a/src/callable.cpp
+++ b/src/callable.cpp
@@ -11,7 +11,7 @@
/**
* Namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Function that is called by the Zend engine every time that a function gets called
@@ -101,7 +101,7 @@ void Callable::process(const std::initializer_list<Argument> &arguments)
for (auto it = begin(arguments); it != arguments.end(); it++)
{
// fill the argument structure
- it->internal()->fill(&_argv[++i]);
+// it->internal()->fill(&_argv[++i]);
}
}
diff --git a/src/callable.h b/src/callable.h
index b6f1e98..293e3aa 100644
--- a/src/callable.h
+++ b/src/callable.h
@@ -14,7 +14,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Class definition
diff --git a/src/extension.cpp b/src/extension.cpp
index 2ed4fa7..2d9ef9f 100644
--- a/src/extension.cpp
+++ b/src/extension.cpp
@@ -9,7 +9,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* If this extension is compiled for a PHP version with multi
@@ -142,43 +142,109 @@ static int request_shutdown(INIT_FUNC_ARGS)
* @param name Name of the extension
* @param version Version number
*/
-Extension::Extension(const char *name, const char *version, const Functions &functions)
+Extension::Extension(const char *name, const char *version) : _ptr(this, name)
{
- // allocate memory
+ // allocate memory (we allocate this on the heap so that the size of the
+ // entry does not have to be defined in the .h file. We pay a performance
+ // price for this, but we pay this price becuase the design goal of the
+ // PHP-C++ library is to have an interface that is as simple as possible
_entry = new zend_module_entry;
- // assign all members (apart from the globals)
- _entry->size = sizeof(zend_module_entry); // size of the data
- _entry->zend_api = ZEND_MODULE_API_NO; // api number
- _entry->zend_debug = ZEND_DEBUG; // debug mode enabled?
- _entry->zts = USING_ZTS; // is thread safety enabled?
- _entry->ini_entry = NULL; // the php.ini record
- _entry->deps = NULL; // dependencies on other modules
- _entry->name = HiddenPointer<Extension>(this, name); // extension name, with a hidden pointer to the extension object
- _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
- _entry->request_shutdown_func = request_shutdown; // shutdown function per request
- _entry->info_func = NULL; // information for retrieving info
- _entry->version = version; // version string
- _entry->globals_size = 0; // size of the global variables
- _entry->globals_ptr = NULL; // pointer to the globals
- _entry->globals_ctor = NULL; // constructor for global variables
- _entry->globals_dtor = NULL; // destructor for global variables
- _entry->post_deactivate_func = NULL; // unknown function
- _entry->module_started = 0; // module is not yet started
- _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
-
- // things that only need to be initialized
+ // assign all members (apart from the globals)
+ _entry->size = sizeof(zend_module_entry); // size of the data
+ _entry->zend_api = ZEND_MODULE_API_NO; // api number
+ _entry->zend_debug = ZEND_DEBUG; // debug mode enabled?
+ _entry->zts = USING_ZTS; // is thread safety enabled?
+ _entry->ini_entry = NULL; // the php.ini record
+ _entry->deps = NULL; // dependencies on other modules
+ _entry->name = _ptr; // extension name, with a hidden pointer to the extension object
+ _entry->functions = NULL; // functions supported by this module (none for now)
+ _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
+ _entry->request_shutdown_func = request_shutdown; // shutdown function per request
+ _entry->info_func = NULL; // information for retrieving info
+ _entry->version = version; // version string
+ _entry->globals_size = 0; // size of the global variables
+ _entry->globals_ptr = NULL; // pointer to the globals
+ _entry->globals_ctor = NULL; // constructor for global variables
+ _entry->globals_dtor = NULL; // destructor for global variables
+ _entry->post_deactivate_func = NULL; // unknown function
+ _entry->module_started = 0; // module is not yet started
+ _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
+
+ // things that only need to be initialized
#ifdef ZTS
- _entry->globals_id_ptr = NULL;
+ _entry->globals_id_ptr = NULL;
#else
- _entry->globals_ptr = NULL;
+ _entry->globals_ptr = NULL;
#endif
+
+}
+
+/**
+ * Destructor
+ */
+Extension::~Extension()
+{
+ // deallocate functions
+ if (_entry->functions) delete[] _entry->functions;
+
+ // deallocate entry
+ delete _entry;
+}
+
+/**
+ * Add a function to the library
+ * @param name Function name
+ * @param function Function object
+ * @return Function
+ */
+Function &Extension::add(const char *name, const Function &function)
+{
+ // add the function to the map
+ return _functions[name] = function;
+}
+
+/**
+ * Retrieve the module entry
+ * @return zend_module_entry
+ */
+zend_module_entry *Extension::module()
+{
+ // check if functions we're already defined
+ if (_entry->functions || _functions.size() == 0) return _entry;
+
+ // allocate memory for the functions
+ zend_function_entry *functions = 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++)
+ {
+ // retrieve entry
+ zend_function_entry *entry = &functions[i];
+
+ // let the function fill the entry
+ it->second.fill(it->first, entry);
+ }
+
+ // last entry should be set to all zeros
+ zend_function_entry *last = &functions[i];
+
+ // all should be set to zero
+ memset(last, 0, sizeof(zend_function_entry));
+
+ // store functions in entry object
+ _entry->functions = functions;
+
+ // return the entry
+ return _entry;
}
/**
diff --git a/src/function.cpp b/src/function.cpp
index cb56d78..8612cf1 100644
--- a/src/function.cpp
+++ b/src/function.cpp
@@ -11,25 +11,83 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
- * Constructor
+ * 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_function(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);
+
+ // wrap the return value
+ Value ret(return_value, true);
+
+ // construct parameters
+ Parameters params(ZEND_NUM_ARGS());
+
+ // call the appropriate object
+ ret = function->invoke(params);
+}
+
+/**
+ * Fill a function entry
+ *
+ * This method is called when the extension is registering itself, when the
+ * function or method introces himself
+ *
* @param name Name of the function
- * @param arguments The arguments that can be passed to the function
+ * @param entry Entry to be filled
*/
-Function::Function(const std::string &name, const std::initializer_list<Argument> &arguments)
+void Function::fill(const char *name, zend_function_entry *entry)
{
- // create callable object
- _callable = new Callable(name, arguments);
+ // fill the members of the entity, and hide a pointer to the current object in the name
+ entry->fname = HiddenPointer<Function>(this, name);
+ entry->handler = invoke_function;
+ entry->arg_info = _arguments->internal();
+ entry->num_args = _arguments->argc();
+
+ // there are no flags like deprecated, private or protected
+ entry->flags = 0;
+
+ // we should fill the first argument as well
+ fill(name, (zend_internal_function_info *)entry->arg_info);
}
/**
- * Destructor
+ * Fill a function entry
+ * @param name Name of the function
+ * @param info Info to be filled
*/
-Function::~Function()
+void Function::fill(const char *name, zend_internal_function_info *info)
{
- if (_callable) delete _callable;
+ // 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<Function>(this, name);
+ info->_name_len = strlen(name);
+ info->_class_name = NULL;
+
+ // number of required arguments, and the expected return type
+ info->required_num_args = _arguments->required();
+ info->_type_hint = _type;
+
+ // we do not support return-by-reference
+ info->return_reference = false;
+
+ // passing by reference is not used
+ info->pass_rest_by_reference = false;
}
/**
diff --git a/src/functions.cpp b/src/functions.cpp
deleted file mode 100644
index f9e0ffb..0000000
--- a/src/functions.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Functions.cpp
- *
- * Implementation for the functions class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace PhpCpp {
-
-/**
- * Constructor
- * @param functions The functions to parse
- */
-Functions::Functions(const std::initializer_list<Function> &functions) : _functions(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
- */
-Functions::~Functions()
-{
- delete[] _entries;
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/includes.h b/src/includes.h
index 28d8b51..1a464e0 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -14,6 +14,8 @@
#include <string>
#include <initializer_list>
#include <vector>
+#include <map>
+#include <memory>
// for debugging
#include <iostream>
@@ -31,12 +33,14 @@
/**
* Include other files from this library
*/
+#include "../include/hiddenpointer.h"
#include "../include/type.h"
#include "../include/request.h"
#include "../include/argument.h"
#include "../include/value.h"
#include "../include/member.h"
#include "../include/arguments.h"
+#include "../include/parameters.h"
#include "../include/function.h"
#include "../include/functions.h"
#include "../include/extension.h"
@@ -46,4 +50,3 @@
*/
#include "callable.h"
#include "arginfo.h"
-#include "hiddenpointer.h"
diff --git a/src/parameters.cpp b/src/parameters.cpp
new file mode 100644
index 0000000..d31f49c
--- /dev/null
+++ b/src/parameters.cpp
@@ -0,0 +1,39 @@
+/**
+ * Parameters.cpp
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2013 Copernica BV
+ */
+#include "includes.h"
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Parameters
+ * @param argc Number of arguments
+ * @param tsrm_ls
+ */
+Parameters::Parameters(int argc TSRMLS_DC)
+{
+ // reserve plenty of space
+ reserve(argc);
+
+ // loop through the arguments
+ for (int i=0; i<argc; i++)
+ {
+ // get the argument
+ zval **arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (argc-i));
+
+ // append value
+ push_back(Value(*arg));
+ }
+}
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/src/value.cpp b/src/value.cpp
index 9224162..f386822 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -29,7 +29,7 @@
/**
* Set up namespace
*/
-namespace PhpCpp {
+namespace Php {
/**
* Constructor (value = NULL)
diff --git a/tests/simple/simple.cpp b/tests/simple/simple.cpp
index b0259ca..a33b220 100644
--- a/tests/simple/simple.cpp
+++ b/tests/simple/simple.cpp
@@ -25,8 +25,11 @@ static std::string my_concat(std::string &a, std::string &b)
return a + b;
}
-Function f({"my_plus", my_plus});
-
+class MyCustomFunction : public Php::Function
+{
+
+
+};
// symbols are exported according to the "C" language
extern "C"
@@ -34,14 +37,25 @@ extern "C"
// export the "get_module" function that will be called by the Zend engine
PHPCPP_EXPORT void *get_module()
{
+ cout << "a" << endl;
+
// create extension
- static PhpCpp::Extension extension("simple","1.0", {
- {"my_plus", my_plus},
- {"my_concat", my_concat}
- });
+ static Php::Extension extension("simple","1.0");
+
+ cout << "b" << endl;
+
+ // define the functions
+// extension.add("my_plus", my_plus);
+// extension.add("my_concat", my_concat);
+ extension.add("my_custom", MyCustomFunction());
+
+ cout << "c" << endl;
+
+ // define classes
+// extension.add("my_class", MyCustomClass());
// return the module entry
- return extension.getEntry();
+ return extension.module();
}
}