CHAPTER 15 – Thread-Safe Resource Manager Macros
By now, you must have noticed the use of macros here and there starting with TSRM, which stands for Thread-Safe Resource Manager. These macros give your extension the possibility of having its own global variables, as previously mentioned. When writing a PHP extension, whether in a multi-process or a multi- threaded environment, you access your extension's global variables via this mechanism. If you want to use global variable accessor macros (such as the MYFILE_G() macro), you need to make sure that the TSRM context information is present in your current function. For performance reasons, the Zend Engine tries to pass around this context as a parameter as much as possible, including to your PHP_FUNCTION() definition. For this reason, when writing code that uses the accessor macro (such as MYFILE_G()) in the scope of PHP_FUNCTION(), you don't have to make any special declarations. However, if your PHP function calls other C functions that need access to the global variables, you must either pass that context to the C function as an extra parameter or you must fetch the context that is slower. To fetch the context, you can just use the TSRMLS_FETCH() at the beginning of a code block in which you need access to the global variables. For example: void myfunc() { TSRMLS_FETCH(); MYFILE_G(myglobal) = 2; } If you want your code to be more optimized, it is better to pass the con- text to your function directly (as mentioned before, it is automatically avail- able to you in PHP_FUNCTION()'s scope). You can do this by using the TSRMLS_C (C for call) and TSRMLS_CC (CC for call and comma) macros. The former should be used when the context is the only parameter, and the latter when it is part of a function that accepts more than one argument. In the latter's case, it may not be the first argument because it places a comma before the context, hence its name. In the function's prototype, you will respectively use the TSRMLS_D and TSRMLS_DC macros to declare that you're receiving the context. Here's the previous example re-written to take advantage of passing the context by parameter: void myfunc(TSRMLS_D) { MYFILE_G(myglobal) = 2; } PHP_FUNCTION(my_php_function) { ... myfunc(TSRMLS_C); ... }
SUMMARY So far, you learned enough about writing PHP extensions to create your own custom extensions. This chapter covered the important fundamentals to writing and understanding PHP extensions. The extension API framework provided by the Zend Engine is extremely rich and allows you to write object- oriented extensions. For many of the advanced features, very little documenta- tion currently exists. Of course, nothing replaces looking at the core PHP extensions bundled with PHP. You can learn a lot from skimming through existing source code, and the fundamentals you have learned in this chapter should allow you to do so. Additional information can be found in the extending PHP chapter of the PHP manual at http://www.php.net/manual/en/zend.php Also, you might want to consider joining the PHP developers mailing list, mailto:inter- nals@lists.php.net, which deals with developing PHP itself. In addition, you should look at a new extension-generating tool called PECL_Gen ( http://pear.php.net/package/PECL_Gen ), which is under development and will have more features than the ext_skel script used in this chapter.