📜 ⬆️ ⬇️

PHP extensions: some interesting features

Writing in C ++ extensions for PHP is not so often, but when it is necessary, it turns out that there are not so many publications and documentation on this topic. Especially if you dig deeper. I will describe several interesting points that I had to find out "the hard way."

Unexpected difficulties await us when calling from the extension code (which, let me remind you, we write in C ++) PHP functions. For this, the call_user_function_ex function is provided, an example of the use of which is not very difficult to find; problems arise if you make its call from a C ++ function that is called from PHP. These functions are declared as follows:

ZEND_FUNCTION(MyFunction) { … } 

')
After making a call to call_user_function_ex beyond its limits, our extension stops compiling.
The answer (and the solution to the problem) lies, of course, in the definition of the ZEND_FUNCTION macro, which adds a couple of parameters to the definition of the function. We have no choice but to pass them to the function where we want to access PHP. It will look like this:

 ZEND_FUNCTION(MyFunction) { ... char *result = myInnerFunction ( CG ( function_table ), tsrm_ls ); ... } char *myInnerFunction ( HashTable *function_table, void ***tsrm_ls ) { ... call_user_function_ex(...); ... } 


Another interesting feature of working with PHP's structures from C ++ is related to what tools the PHP developers have provided us with tools for working with associative arrays. In PHP, we are used to easily operate with such arrays, to create multi-storey structures. In C ++, working with them will turn into a nightmare: of course, the corresponding API methods are provided, but to call them too convenient the language will not turn. For example, a cycle running through one array level would look like this:

 for (zend_hash_internal_pointer_reset_ex (arr_hash, &pointer); zend_hash_get_current_data_ex (arr_hash, (void**) &data, &pointer ) == SUCCESS; zend_hash_move_forward_ex (arr_hash, &pointer)) { ... } 


If in C ++ you need to work with a multi-storey array, then using it with these tools, frankly, you don’t run up.
What can be offered in return? A rather simple and clear option is to deploy a multi-storey associative array in two simple two-dimensional ones. One of them will contain “packed” keys, the second - values. You can pack the keys into strings where the keys of different levels will be separated by some symbol. Imagine this array in PHP:

 $a = Array ( "user" => Array ( Array ( "name" => "Ivanov", "age" => 28), Array ( "name" => "Petrov", "age" => 23) ) ); 


In C ++, you can quickly find values ​​in it if you pack it like this:

 string keys[] = { "user_0_name", "user_0_age", "user_1_name", "user_1_age" }; string values[] = { "Ivanov", "28", "Petrov", "23" }; 

Source: https://habr.com/ru/post/160093/


All Articles