internals:engine

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
internals:engine [2010/04/25 20:11] derickinternals:engine [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 8: Line 8:
   * the pass_two() changes indexes into pointers so during execution they are accessible by: <code>opline->op1.zv</code>   * the pass_two() changes indexes into pointers so during execution they are accessible by: <code>opline->op1.zv</code>
  
 +===== Objects =====
 +See [[internals:engine:objects|here]].
  
 ===== FAQ ===== ===== FAQ =====
Line 47: Line 49:
   [11:59am] scoates: and the hashtable will automatically grow on _add, right? the length passed to init is just a hint?   [11:59am] scoates: and the hashtable will automatically grow on _add, right? the length passed to init is just a hint?
   [11:59am] johannes_: right   [11:59am] johannes_: right
- 
 ===== Unsorted ===== ===== Unsorted =====
  
 Add your random stuff here. I'll move it/update it/fix it (Derick) Add your random stuff here. I'll move it/update it/fix it (Derick)
 +
 +How to get %%__LINE__ and __FILE__%%?
 +  * zend_get_executed_filename() and zend_get_executed_lineno()
 +
 +How do I detect the SAPI?
 +  * The fastest way [to detect CLI] would be: if (sapi_module.phpinfo_as_text) { ... }
 +  * sapi_module is a true global, not a TSRM protected one
 +  * sapi_module.name and sapi_module.pretty_name contain the name as char*
 +  * sapi_module.phpinfo_as_text is a flag which can be set by different SAPIs to request text only phpinfo() output, currently only CLI and embed do that afaik, CGI does not.
 +
 +
 +==== Extension Globals =====
 +
 +To use extension globals (which are either true globals or thread local globals, depending on whether ZTS is enabled), follow these steps:
 +
 +- In php_extname.h, declare which global variables you need with:
 +
 +<code>
 +ZEND_BEGIN_MODULE_GLOBALS(extname)
 + int var1;
 + char *var2;
 + ....
 +ZEND_END_MODULE_GLOBALS(extname)
 +</code> 
 +
 +This will declare a structure (typedef'd to zend_extname_globals) that will hold all your globals.
 +
 +- In php_extname.h, add <code>ZEND_EXTERN_MODULE_GLOBALS(extname);</code>. This will produce an allusion that will allow you to access the globals from every compile unit that includes php_extname.h In particular, this produces an allusion to an integer named extname_globals_id in ZTS builds or directly to a zend_extname_globals named extname_globals in non-ZTS builds.
 +
 +- In php_extname.h, define a macro named EXTNAME_G, like this:
 +<code>
 +#ifdef ZTS
 +# define EXTNAME_G(v) TSRMG(extname_globals_id, zend_extname_globals *, v)
 +#else
 +# define EXTNAME_G(v) (extname_globals.v)
 +#endif
 +</code>
 +
 +This will allow you to access the globals in a consistent manner in both ZTS and non-ZTS builds, like this:
 +
 +<code>EXTNAME_G(var1)</code>
 +
 +- Now that you have declared the type that aggregates the globals and the variable that holds the globals, you must define the globals. In extname.c, add
 +
 +<code>ZEND_DECLARE_MODULE_GLOBALS(extname);</code>
 +
 +This produces a tentative definition of extname_globals_id or extname_globals (depending on whether it's a ZTS or non-ZTS build).
 +
 +- If you needn't do any startup operations on your variables, you would already have function extension globals in non-ZTS builds. Tipically, you will also want to initialize some extension globals (for instance, to allocate some memory for the var2 extension global above) -- this is done with globals constructors and destructors. To make it work in ZTS builds and allow such operations, add the following to your zend_module_entry:
 +
 +<code>
 +zend_module_entry extname_module_entry = {
 + ...
 + ZEND_MODULE_INFO_N(extname),
 + PHP_EXTNAME_VERSION,
 + ZEND_MODULE_GLOBALS(extname),
 + ZEND_MODULE_GLOBALS_CTOR_N(extname), //may be NULL
 + ZEND_MODULE_GLOBALS_DTOR_N(extname), //may be NULL
 + ...
 +}
 +</code>
 +
 +Note: do not use ZEND_INIT_MODULE_GLOBALS/ts_allocate_id. If used a shared extension, they will provoke an attempt to call the destructor after the module has been unloaded! Also, for all that is holy, do NOT initialize globals on MINIT (EXTNAME_G(var_ptr) = NULL), that won't work correctly in ZTS as it won't initialize the value in all threads.
 +
 +- Now define the constructor and destructor functions:
 +
 +<code>
 +ZEND_MODULE_GLOBALS_CTOR_D(extname)
 +{
 + extname_globals->arg2 = pemalloc(1024, 1);
 +}
 +
 +ZEND_MODULE_GLOBALS_DTOR_D(extname)
 +{
 + pefree(extname_globals->arg2, 1);
 +}
 +</code>
 +
 +The globals constructor and destructor are NOT execute per-request, they are part of the module startup/shutdown. The globals can store data across requests. If you need to do per-request operations to the globals, use module-activate and module-deactivate callbacks.
 +
 +Note: ZEND_MODULE_GLOBALS_CTOR_D will declare a function as receiving a zend_extname_globals*, not void* and zend_module_entry is supposed to contain a function pointer type that receives void*. I think this violates the C standard (the declarations are incompatible), but should however by safe since the arguments have the same size.
internals/engine.1272226272.txt.gz · Last modified: 2017/09/22 13:28 (external edit)