I previously discussed how to use extension api for PHP here. To illustrate the use of it, I will discuss how it can be implemented on exif and mbstring extensions. (Exif depends on mbstring and uses functions php_mb_check_encoding_list and php_mb_convert_encoding)
As also mentioned in the previous blog post, you can find the details about the status of the project here. The source code is available at the git repository : git://github.com/vpj/PHP-Extension-API.git, and some sample test code which uses the interface : git://github.com/vpj/PHP_EXT_API_Tests.git
How to register APIs – mbstring
You should create a structure with the API functions.
1 2 3 4 | static struct { int (*check_encoding_list)(const char * TSRMLS_DC); char * (*convert_encoding)(const char *, size_t, const char *, const char *, size_t * TSRMLS_DC); } mbstring_eapi = {php_mb_check_encoding_list, php_mb_convert_encoding}; |
I used a global variable for this.
Then, you should register the API during module initialization. That is, following piece of code should be included in MINIT.
1 | zend_eapi_register("mbstring", "1.0", (void *)&mbstring_eapi, sizeof(mbstring_eapi)); |
Registering the API is pretty simple, but there might be some issues when using it in exif.
Setting up callback function – exif
First we should define the structure of the API.
1 2 3 4 5 6 | typedef struct { int (*check_encoding_list)(const char * TSRMLS_DC); char * (*convert_encoding)(const char *, size_t, const char *, const char *, size_t * TSRMLS_DC); } mbstring_eapi_struct; static mbstring_eapi_struct *mbstring_eapi; |
Here’s the callback function.
1 2 3 4 5 6 7 8 | EAPI_CALLBACK_FUNCTION(mbstring_eapi_callback) { TSRMLS_FETCH(); mbstring_eapi = pemalloc(sizeof(mbstring_eapi_struct), 1); *mbstring_eapi = *((mbstring_eapi_struct*)api); REGISTER_INI_ENTRIES(); } |
The callback function is named mbstring_eapi_callback. We are calling REGISTER_INI_ENTRIES from the callback, since OnUpdate event handlers for INI entries use check_encoding_list function. If INIs were registered from MINIT the event handlers will be executed before the extension api callback, so we are delaying the INI registration. Since REGISTER_INI_ENTRIES require TRSMLS we fetch those threading information using TSRMLS_FETCH() at the begining of the callback function.
The callback should be registered in MINIT.
1 2 | EAPI_SET_CALLBACK("mbstring", "1.0", mbstring_eapi_callback); mbstring_eapi = NULL; |
We are left with changing the mbstring function calls. I’ll include the changed code in OnUpdateEncode; rest is similar.
1 2 3 4 5 6 7 8 9 10 11 | ZEND_INI_MH(OnUpdateEncode) { if(mbstring_eapi) { if (new_value && strlen(new_value) && !mbstring_eapi->check_encoding_list(new_value TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal encoding ignored: '%s'", new_value); return FAILURE; } } return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); } |

Recent Comments