summaryrefslogtreecommitdiff
path: root/src/extension.cpp
blob: 2ed4fa7be98565185722932efb09850c2eb7e2db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
 *  Extension.cpp
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2013 Copernica BV
 */
#include "includes.h"

/**
 *  Set up namespace
 */
namespace PhpCpp {

/**
 *  If this extension is compiled for a PHP version with multi
 *  threading support, we need an additional header file
 */
#ifdef ZTS
#include "TSRM.h"
#endif

/**
 *  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
 */
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) {}



/**
 *  Helper method to get back the current extension object
 *  @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);

	// the pointer to the extension is hidden in front of the name
	return HiddenPointer<Extension>(module->name);
}

/**
 *  Function that is called when the extension initializes
 *  @param  type        Module type
 *  @param  number      Module number
 *  @return int         0 on success
 */
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(get_extension()->initialize());
}

/**
 *  Function that is called when the extension is about to be stopped
 *  @param  type        Module type
 *  @param  number      Module number
 *  @return int
 */
static int extension_shutdown(SHUTDOWN_FUNC_ARGS)
{
    // finalize the extension
    return BOOL2SUCCESS(get_extension()->finalize());
}

/**
 *  Function that is called when a request starts
 *  @param  type        Module type
 *  @param  number      Module number
 *  @return int         0 on success
 */
static int request_startup(INIT_FUNC_ARGS)
{
    // create the request
    return BOOL2SUCCESS(get_extension()->startRequest());
}

/**
 *  Function that is called when a request is ended
 *  @param  type        Module type
 *  @param  number      Module number
 *  @return int         0 on success
 */
static int request_shutdown(INIT_FUNC_ARGS)
{
    // end the request
    return BOOL2SUCCESS(get_extension()->endRequest());
}


/**
 *  Constructor
 *  @param  name        Name of the extension
 *  @param  version     Version number
 */
Extension::Extension(const char *name, const char *version, const Functions &functions)
{
    // allocate memory
    _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
#ifdef ZTS
	_entry->globals_id_ptr = NULL;
#else
	_entry->globals_ptr = NULL;
#endif
}

/**
 *  End of namespace
 */
}