writing extensions best practice, pass an object as parameter

php.internals

Torsten Rosenberger

9 years ago
Hello List I'm new to C and writing extensions I hope this ist the right list. I want to port the PEAR HTML_Template_Sigma Class to an PHP extension. I startet with the old book 'Building custom PHP Extensions' found now newer one. At the moment i have some class functions in my extension as they are in the PHP Class. in the PHP Class are some callback functions registert $this->setCallbackFunction('e', array(&$this, '_htmlentities')); $this->setCallbackFunction('u', 'urlencode'); the easier callback's to a php function i managed with this code zval tplFunction; ZVAL_STRING(&tplFunction,"u"); zval callback; ZVAL_STRING(&callback,"urlencode"); zend_call_method_with_2_params ( obj,Template_Sigma, NULL, "setcallbackfunction", NULL, &tplFunction, &callback); but how can i pass the object from a private method of the PHP extension class to the setcallbackfunction as it is down in PHP with array(&$this, '_htmlentities') So i try doing some bench :( Testing with php7. i call the class constructor from the extension 1000 times and also the same with the PHP class. $x = new HTML_Template_Sigma("dir","dir_cache"); so the PHP Class with opcache ist equal faste as my extension. My goal was to write the class as an extension to get faster. The last question should I use call_user_function or write this function in C. for example the private methode _jsEscape uses the PHP strtr and the second parameter is an array so the internal php_strtr_array function is called. Should I instead call the php_strtr function multiple times ? Best Regards Torsten

Adam Baratz

9 years ago
> > but how can i pass the object from a private method of the PHP extension >
class to the setcallbackfunction as it is down in PHP with
> > array(&$this, '_htmlentities') >
I usually find reading the source for standard library functions to be helpful for learning how to do things. array_map could help with capturing a callable and then doing something with it: https://github.com/php/php-src/blob/master/ext/standard/array.c#L6005 so the PHP Class with opcache ist equal faste as my extension.
> My goal was to write the class as an extension to get faster. >
Is the constructor where the bulk of the computation happens? Given that this is a templating tool, it's probably during render. My guess of what you'd get out of rewriting in C is greater control over string manipulation and related memory allocation. That said, if you're hitting performance issues, I might suggest looking into another templating tool that's more actively maintained. Extensions are generally harder to maintain than userland code. If you succeed in writing a faster version of this tool, this could turn into a "now you have two problems" situation[1]. If at all possible, it'd be better to let an existing community solve performance issues for you. The last question should I use call_user_function or write this function
> in C. >
Call the internal function directly for less overhead. Hope this helps! Adam --- [1] http://regex.info/blog/2006-09-15/247

Johannes Schlueter

9 years ago
On Wed, 2017-01-18 at 09:17 +0100, Torsten Rosenberger wrote:
> Hello List > > I'm new to C and writing extensions > I hope this ist the right list. > > I want to port the PEAR HTML_Template_Sigma Class to an PHP > extension. I startet with the old book 'Building custom PHP Extensions' > found now newer one. > > At the moment i have some class functions in my extension as they are in > the PHP Class. > > in the PHP Class are some callback functions registert > > $this->setCallbackFunction('e', array(&$this, '_htmlentities'));
Using a reference here is useless. Just put $this in the aray.
> $this->setCallbackFunction('u', 'urlencode'); > > the easier callback's to a php function i managed with this code > > > zval tplFunction; > ZVAL_STRING(&tplFunction,"u"); > zval callback; > ZVAL_STRING(&callback,"urlencode"); > > zend_call_method_with_2_params ( obj,Template_Sigma, NULL, > "setcallbackfunction", NULL, &tplFunction, &callback); > > > but how can i pass the object from a private method of the PHP extension > class to the setcallbackfunction as it is down in PHP with > > array(&$this, '_htmlentities') > > > > So i try doing some bench :( > Testing with php7. > > i call the class constructor from the extension 1000 times and also the > same with the PHP class. > > $x = new HTML_Template_Sigma("dir","dir_cache");
I don't fully understand what exactly you want to do. If you want to pass an array with two values to zend_call_method you have to build the array (array_init, add_next_index_zval, add_next_index_stringl etc.) and eventually free this again. For a private member you of course have to mind the context which is given as class entry via the second argument to zend_call_method_with_2_params If you want to receive a callback from a user see the "f" modifier for zend_parse_paramters, when storing this you probably have to increase a reference count on some object. In https://github.com/php-test-helpers/php-test-helpers/blob/master/test_helpers.c#L396 I did this, while that code might not work in PHP 7.
> so the PHP Class with opcache ist equal faste as my extension. > My goal was to write the class as an extension to get faster. > > > > > The last question should I use call_user_function or write this function > in C. > > for example > the private methode _jsEscape uses the PHP strtr and the second > parameter is an array so the internal php_strtr_array function is > called. Should I instead call the php_strtr function multiple times ?
If the extension primarily is just calling userspace-exported functions there's not much performance gain to win. If you can do more complex operations in C there can be some gain, though. johannes