All we have right now is a weak extension: it accepts no parameters, which is quite dull and therefore quite easy. What we're going to do is modify it so that we can pass to it the string we want to print out as a parameter - that's much more interesting!
All of the housekeeping work is done already, so we are now just working on the hello_print() function itself in hello.c. Actually accepting parameters is done through the zend_parse_parameters() function, which handles parameters coming into a function very easily - developers who have written Python extensions before will be right at home with it.
This function looks odd at first, thanks largely to the use of macros in a confusing way. As with before, it's easiest if I just show you the code and then explain it, so here goes:
PHP_FUNCTION(hello_print)
{
char *str = NULL;
int str_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
return;
}
php_printf("%s", str);
}
First up, we declare a "char *" (pointer to a character, or character array as is this case) called str and an integer called str_len. These will be used to store the string that gets passed in - str_len is required because PHP also passes in the length of the string.
Then we come to the zend_parse_parameters() call. The first two parameters are ZEND_NUM_ARGS() and TSRMLS_CC - the exclusion of a comma between the two is on purpose, and is resolved when the macros are expanded. Confusing I know, but that's how it works! The ZEND_NUM_ARGS() macro helpfully passes in the nubmer of arguments that were actually passed in, and the TSRMLS_CC stands for Thread Safe Resource Manager Local Storage Call with Comma, and ensures thread safety for your extension. The reason it is "with Comma" goes back to what I was saying about it being parameter two - it is preceded by a comma.
The nice thing about zend_parse_parameters() comes in the next parameter. In the code example we have "s", which means "we want just one string". If the function gets no parameters, PHP will automatically flag an error and exit. If it gets passed with three parameters, the same happens. Most importantly, though, is that if the function is passed with one integer parameter, zend_parse_parameters() will silently convert that integer into the string as we requested. It will then place the string value into str, and its length into str_len. Perfect! Note that ampersand (&) are required before the variables because they must be passed in as pointers.
So, if zend_parse_parameters() fails, we exit. If not, we just go ahead and print out the string - easy or what? Modify your script to pass in something to print out (make sure and include a "\n" in there to add a new line!), and go ahead and recompile and retest.
That, too, was very easy, so let's swiftly move on to adding a second parameter to our function: how many times to print out the string passed in as parameter one. Don't forget to change the prototype in the source code as you go, mind you!
This time we need to pass the same str and str_len to zend_parse_parameters(), but we also need a repeat value. Right now, we specify "s" as the variables to accept so that we get a string through, but we're going to change that to "sl", which means "a string and a long integer". Then we just need to take the repeat count and loop through it, printing out the message. Sound easy? It is!
/* {{{ proto void hello_print(string message, int repeat)
* Print a message to show how much PHP extensions rock */
PHP_FUNCTION(hello_print)
{
int str_len;
char *str = NULL;
int repeat;
int i;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &str, &str_len, repeat) == FAILURE) {
return;
}
for (i = 0; i < repeat; ++i) {
php_printf("%s", str);
}
}
/* }}} */
Yeah, I know - that was really easy too! A more interesting thing to tackle is factorial calculation, because really it requires two functions to work: one for others to call from their PHP scripts, and another we use internally for recursive calling.
Want to learn PHP 7?
Hacking with PHP has been fully updated for PHP 7, and is now available as a downloadable PDF. Get over 1200 pages of hands-on PHP learning today!
If this was helpful, please take a moment to tell others about Hacking with PHP by tweeting about it!
Next chapter: Factorials in C >>
Previous chapter: Hello world - in C!
Jump to:
Home: Table of Contents
Copyright ©2015 Paul Hudson. Follow me: @twostraws.