summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-08-25 17:40:03 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-08-25 17:40:03 +0200
commite14055694478d70e58b5fc653b08a9a514bbc455 (patch)
treeab47d723699a7fe86f47f68c182ab695bf9b3bab /src
parente838e180f5bbcf19e7235f30311645e942ff92d2 (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/Makefile2
-rw-r--r--src/arginfo.h97
-rw-r--r--src/argument.cpp60
-rw-r--r--src/callable.cpp87
-rw-r--r--src/callable.h146
-rw-r--r--src/config.m44
-rw-r--r--src/extension.cpp11
-rw-r--r--src/function.cpp49
-rw-r--r--src/functions.h80
-rw-r--r--src/includes.h17
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"
+