@@ -4,4 +4,211 @@ Extension skeleton
4
4
Here we detail what a PHP extension look like, and how to generate a skeleton using some tools. That will allow us to
5
5
use a skeleton code and hack into it, instead of creating every needed piece by hand from scratch.
6
6
7
- We'll also detail how you could/should organize your extension files.
7
+ We'll also detail how you could/should organize your extension files, how the engine loads them, and basically
8
+ everything you need to know about a PHP extension.
9
+
10
+ How the engine loads extensions
11
+ *******************************
12
+
13
+ You remember :doc: `the chapter about building PHP extensions <../build_system/building_extensions >`, so you know how
14
+ to compile/build it and install it.
15
+
16
+ When PHP starts, it quickly goes to parse its different INI files. If present, those later may declare extensions to
17
+ load using the *"extension=some_ext.so" * line reference.
18
+ PHP then collects every extension parsed from INI configuration, and will try to load them.
19
+
20
+ To load extensions, `libdl <https://en.wikipedia.org/wiki/Dynamic_loading >`_ and its
21
+ `dlopen()/dlsym() <http://www.unix.com/man-page/All/3lib/libdl/ >`_ functions are used.
22
+
23
+ The symbol that is looked for is the ``get_module() `` symbol, that means that you extension must export it to be loaded.
24
+ This is usually the case, as if you used the skeleton script (we'll foresee it in a minute), then that later generated
25
+ code using the ``ZEND_GET_MODULE(your_ext) `` macro, which looks like::
26
+
27
+ #define ZEND_GET_MODULE(name) \
28
+ BEGIN_EXTERN_C()\
29
+ ZEND_DLEXPORT zend_module_entry *get_module(void) { return &name##_module_entry; }\
30
+ END_EXTERN_C()
31
+
32
+ Like you can see, that macro when used declares a global symbol : the get_module() function that will get called by the
33
+ engine once wanting to load your extension.
34
+
35
+ .. note :: The source code PHP uses to load extensions is located into
36
+ `ext/standard/dl.c <https://github.com/php/php-src/blob/27d681435174433c3a9b0b8325361dfa383be0a6/ext/
37
+ standard/dl.c#L90> `_
38
+
39
+ What is an extension ?
40
+ **********************
41
+
42
+ A PHP extension, not to be confused with a :doc: `Zend extension <zend_extensions >`, is set up by the usage of a
43
+ ``zend_module_entry `` structure::
44
+
45
+ struct _zend_module_entry {
46
+ unsigned short size; /*
47
+ unsigned int zend_api; * STANDARD_MODULE_HEADER
48
+ unsigned char zend_debug; *
49
+ unsigned char zts; */
50
+
51
+ const struct _zend_ini_entry *ini_entry; /* Unused */
52
+ const struct _zend_module_dep *deps; /* Module dependencies */
53
+ const char *name; /* Module name */
54
+ const struct _zend_function_entry *functions; /* Module published functions */
55
+
56
+ int (*module_startup_func)(INIT_FUNC_ARGS); /*
57
+ int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); *
58
+ int (*request_startup_func)(INIT_FUNC_ARGS); * Lifetime functions (hooks)
59
+ int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); *
60
+ void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); */
61
+
62
+ const char *version; /* Module version */
63
+
64
+ size_t globals_size; /*
65
+ #ifdef ZTS *
66
+ ts_rsrc_id* globals_id_ptr; *
67
+ #else * Globals management
68
+ void* globals_ptr; *
69
+ #endif *
70
+ void (*globals_ctor)(void *global); *
71
+ void (*globals_dtor)(void *global); */
72
+
73
+ int (*post_deactivate_func)(void); /* Rarely used lifetime hook */
74
+ int module_started; /* Has module been started (internal usage) */
75
+ unsigned char type; /* Module type (internal usage) */
76
+ void *handle; /* dlopen() returned handle */
77
+ int module_number; /* module number among others */
78
+ const char *build_id; /* build id, part of STANDARD_MODULE_PROPERTIES_EX */
79
+ };
80
+
81
+ The four first parameters have already been explained in
82
+ :doc: `the building extensions chapter <../build_system/building_extensions >`. They are usually filled-in using the
83
+ ``STANDARD_MODULE_HEADER `` macro.
84
+
85
+ The ``ini_entry `` vector is actually unused. You :doc: `register INI entries <ini_settings >` using special macros.
86
+
87
+ Then you may declare dependencies, that means that your extension could need another extension to be loaded before it,
88
+ or could declare a conflict with another extensions. This is done using the ``deps `` field. In reality, this is very
89
+ ucommonly used, and more generally it is a bad pactice to create dependencies accross PHP extensions.
90
+
91
+ After that you declare a ``name ``. Nothing to say, this name is the name of your extension (which can be different from
92
+ the name of its own *.so * file). Take care the name is case sensitive in most operations, we suggest you use something
93
+ short, lower case, with no spaces (to make things a bit easier).
94
+
95
+ Then come the ``functions `` field. It is a pointer to some PHP functions that extension wants to register into
96
+ the engine. We talked about that :doc: `in a dedicated chapter <php_functions >`.
97
+
98
+ Keeping-on come the 5 lifetime hooks. :doc: `See their dedicated chapter <php_lifecycle >`.
99
+
100
+ Your extension may publish a version number, as a ``char * ``, using the ``version `` field. This field is only read as
101
+ part of your extension informations, that is by phpinfo() or by the reflection API as
102
+ ``ReflectionExtension::getVersion() ``.
103
+
104
+ We next see a lot of fields about globals. Globals management :doc: `has a dedicated chapter <globals_management >`.
105
+
106
+ Finally the ending fields are usually part of the ``STANDARD_MODULE_PROPERTIES `` macro and you don't have to play with
107
+ them by hand. The engine will give you a ``module_number `` for its internal management, and the extension type will be
108
+ set to ``MODULE_PERSISTENT ``. It could be ``MODULE_TEMPORARY `` as if you extension were loaded using PHP's userland
109
+ ``dl() `` function, but that use-case is very uncommon, doesn't work with every SAPI and temporary extensions usually
110
+ lead to many problems into the engine.
111
+
112
+ Generating extension skeleton with scripts
113
+ ******************************************
114
+
115
+ Now we'll see how to generate an extension skeleton so that you may start a new extension with some minimal content
116
+ and structure you won't be forced to create by hand from scratch.
117
+
118
+ the skeleton generator script is located into
119
+ `php-src/ext/ext_skel <https://github.com/php/php-src/blob/27d681435174433c3a9b0b8325361dfa383be0a6/ext/ext_skel >`_ and
120
+ the structure it uses as a template is stored into
121
+ `php-src/ext/skeleton <https://github.com/php/php-src/tree/27d681435174433c3a9b0b8325361dfa383be0a6/ext/skeleton >`_
122
+
123
+ .. note :: The script and the structure move a little bit as PHP versions move forward.
124
+
125
+ You can analyze those scripts to see how they work, but the basic usage is:
126
+
127
+ .. code-block :: shell
128
+
129
+ > cd /tmp
130
+ /tmp> /path/to/php/ext/ext_skel --skel=/path/to/php/ext/skeleton --extname=pib
131
+ [ ... generating ... ]
132
+ /tmp> tree pib/
133
+ pib/
134
+ ├── config.m4
135
+ ├── config.w32
136
+ ├── CREDITS
137
+ ├── EXPERIMENTAL
138
+ ├── php_pib.h
139
+ ├── pib.c
140
+ ├── pib.php
141
+ └── tests
142
+ └── 001.phpt
143
+ /tmp>
144
+
145
+ You can see a very basic an minimal structure that got generated. You've learnt in the building extension chapter that
146
+ the to-be-compiled files of your extension must be declared into *config.m4 *. The skeleton only generated
147
+ *<your-ext-name>.c * file. For the example, we called the extension *"pib" * so we got a *pib.c * file and we must
148
+ uncomment the *--enable-pib * line in *config.m4 * for it to get compiled.
149
+
150
+ Every C file comes with a header file (usually). Here, the structure is *php_<your-ext-name>.h * , so *php_pib.h * for
151
+ us. Don't change that name, the building system expects such a naming convention for the header file.
152
+
153
+ You can see that a minimal test structure has been generated as well.
154
+
155
+ Let's open *pib.c *. In there, everything is commented out, so we won't have too many lines to write here.
156
+
157
+ Basically, we can see that the module symbol needed by the engine to load our extension is published here::
158
+
159
+ #ifdef COMPILE_DL_PIB
160
+ #ifdef ZTS
161
+ ZEND_TSRMLS_CACHE_DEFINE()
162
+ #endif
163
+ ZEND_GET_MODULE(pib)
164
+ #endif
165
+
166
+ The ``COMPILE_DL_<YOUR-EXT-NAME> `` macro is defined if you pass *--enable-<my-ext-name> * flag to configure script. We
167
+ also see that in case of ZTS mode, the TSRM local storage pointer is defined as part of ``ZEND_TSRMLS_CACHE_DEFINE() ``
168
+ macro.
169
+
170
+ After that, there is nothing more to say as everything is commented out and should be clear to you.
171
+
172
+ Publishing API
173
+ **************
174
+
175
+ If we open the header file, we can see those lines::
176
+
177
+ #ifdef PHP_WIN32
178
+ # define PHP_PIB_API __declspec(dllexport)
179
+ #elif defined(__GNUC__) && __GNUC__ >= 4
180
+ # define PHP_PIB_API __attribute__ ((visibility("default")))
181
+ #else
182
+ # define PHP_PIB_API
183
+ #endif
184
+
185
+ Those lines define a macro named ``PHP_<EXT-NAME>_API `` (for us ``PHP_PIB_API ``) and it resolves to the
186
+ `GCC custom attribute <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes >`_
187
+ visibility("default").
188
+
189
+ In C, you can tell the linker to hide every symbol from the final object. This is what's done in PHP, for every
190
+ symbol, not only static ones (which are by definition not published).
191
+
192
+ .. warning :: The default PHP compilation line tells the compiler to hide every symbol and not export them.
193
+
194
+ You should then "unhide" the symbols you'd like your extension to publish for those to be used in other extensions or
195
+ other parts of the final ELF file.
196
+
197
+ .. note :: Remember that you can read published and hidden symbol of an ELF using ``nm`` under Unix.
198
+
199
+ We can't explain thoses concepts in deep here, perhaps such links could help you ?
200
+
201
+ * https://gcc.gnu.org/wiki/Visibility
202
+ * http://www.iecc.com/linker/linker10.html
203
+ * https://www.akkadia.org/drepper/dsohowto.pdf
204
+ * http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html
205
+ * https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html
206
+
207
+ So basically, if you want a C symbol of yours to be publicly available to other extensions, you should declare it
208
+ using the special ``PHP_PIB_API `` macro. The traditionnal use-case for that is to publish the classes symbols
209
+ (``zend_class_entry* `` type) so that other extensions can hook into your own published classes and replace some of their
210
+ handlers.
211
+
212
+ .. note :: Please, note that this only works with the traditionnal PHP. If you use
213
+ :doc: `a PHP from a Linux distribution <../build_system/building_php >`, those are patched to resolve symbols
214
+ at load time and not lazilly, thus this trick doesn't work.
0 commit comments