summaryrefslogtreecommitdiff
path: root/src/extension.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/extension.cpp')
-rw-r--r--src/extension.cpp176
1 files changed, 112 insertions, 64 deletions
diff --git a/src/extension.cpp b/src/extension.cpp
index c995f0b..ee22794 100644
--- a/src/extension.cpp
+++ b/src/extension.cpp
@@ -12,35 +12,79 @@
namespace PhpCpp {
/**
- * Pointer to the one and only extension
- * @var Extension
+ * If this extension is compiled for a PHP version with multi
+ * threading support, we need an additional header file
*/
-static Extension *extension;
+#ifdef ZTS
+#include "TSRM.h"
+#endif
/**
- * Constructor
- * @param name Name of the extension
- * @param version Version number
+ * 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
+ * pointer that is passed and should be forwarded to every thinkable
+ * 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
+ * to assign this object somewhere, so that's what we do in this
+ * one and only global variable
*/
-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;
-}
+ZEND_BEGIN_MODULE_GLOBALS(phpcpp)
+ Request *request;
+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
+ * structure above.
+ */
+#ifdef ZTS
+#define REQUEST_G(v) TSRMG(phpcpp_globals_id, zend_phpcpp_globals *, v)
+#else
+#define REQUEST_G(v) (phpcpp_globals.v)
+#endif
+
+/**
+ * We're almost there, we now need to declare an instance of the
+ * structure defined above (if building for a single thread) or some
+ * sort of impossible to understand magic pointer-to-a-pointer (for
+ * multi-threading builds). We make this a static variable because
+ * this already is bad enough.
+ */
+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
+ */
+static void php_phpcpp_init_globals(zend_phpcpp_globals *globals) {}
+
+/**
+ * The extension is a sort of singleton, so we keep one pointer to it here
+ * @var Extension
+ */
+static Extension *extension = nullptr;
+
/**
- * Destructor
+ * Helper method to get back the current extension object
+ * @return Extension
*/
-Extension::~Extension()
+static Extension *get_extension()
{
- // deallocate functions
- delete _functions;
-
- // deallocate entry
- if (_entry) delete _entry;
+ // 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);
}
/**
@@ -51,8 +95,14 @@ Extension::~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 the extension
- return BOOL2SUCCESS(extension->initialize());
+ return BOOL2SUCCESS(get_extension()->initialize());
}
/**
@@ -63,10 +113,8 @@ static int extension_startup(INIT_FUNC_ARGS)
*/
static int extension_shutdown(SHUTDOWN_FUNC_ARGS)
{
- std::cout << "extension_shutdown" << std::endl;
-
// finalize the extension
- return BOOL2SUCCESS(extension->finalize());
+ return BOOL2SUCCESS(get_extension()->finalize());
}
/**
@@ -78,7 +126,7 @@ static int extension_shutdown(SHUTDOWN_FUNC_ARGS)
static int request_startup(INIT_FUNC_ARGS)
{
// create the request
- return BOOL2SUCCESS(extension->startRequest());
+ return BOOL2SUCCESS(get_extension()->startRequest());
}
/**
@@ -90,49 +138,49 @@ static int request_startup(INIT_FUNC_ARGS)
static int request_shutdown(INIT_FUNC_ARGS)
{
// end the request
- return BOOL2SUCCESS(extension->endRequest());
+ return BOOL2SUCCESS(get_extension()->endRequest());
}
+
/**
- * Retrieve a pointer to the entry
- * @return zend_module_entry
+ * Constructor
+ * @param name Name of the extension
+ * @param version Version number
*/
-zend_module_entry *Extension::entry()
+Extension::Extension(const char *name, const char *version, const Functions &functions)
{
- // already initialized?
- if (_entry) return _entry;
-
- // allocate now
- _entry = new zend_module_entry;
-
- // assign all members
- _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 = _name; // extension name
- _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
-
- // done
- return _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
+#ifdef ZTS
+ _entry.globals_id_ptr = NULL;
+#else
+ _entry.globals_ptr = NULL;
+#endif
}
/**