CHAPTER 15 – Returning Values from PHP Functions
The extension API includes a rich collection of macros that allows you to return values from your functions. These macros come in two main flavors. The first is of the form RETVAL_type(), which sets the return value but your C code keeps on executing. This is usually used if you still want to do some clean- ing up before returning control over to the scripting engine. You will then need to use the C return statement "return;" to return to PHP. The latter, which are the more popular macros, are of the form RETURN_type(), which set the return type and return control back to PHP. Table 15.2 explains most of the existing macros. Table 15.2 Return Values Macros Setting the Return Value Macro Return Type and and Ending the Function Setting the Return Value Parameters RETURN_LONG(l) RETVAL_LONG(l) Integer. RETURN_BOOL(b) RETVAL_BOOL(b) Boolean (1 or 0). RETURN_NULL() RETVAL_NULL() Null. RETURN_DOUBLE(d) RETVAL_DOUBLE(d) Floating point. RETURN_STRING(s, dup) RETVAL_STRING(s, dup) String. If dup is 1, the engine will duplicate s using estr- dup() and will use the copy. If dup is 0, it will use s. RETURN_STRINGL(s, l, RETVAL_STRINGL(s, l, dup) String value of length l. Same dup) as the previous entry, but faster when duplicating because the length of s is specified by you in the macro. RETURN_TRUE RETVAL_TRUE Returns the Boolean value true. Note that this macro doesn't have braces. RETURN_FALSE RETVAL_FALSE Returns the Boolean value true. Note that this macro doesn't have braces. RETURN_RESOURCE(r) RETVAL_RESOURCE(r) Resource handle. Completing self_concat() Now that you have learned how to allocate memory and return values from PHP extension functions, we can complete the code for self_concat(): /* {{{ proto string self_concat(string str, int n) */ PHP_FUNCTION(self_concat) } char *str = NULL; int argc = ZEND_NUM_ARGS(); int str_len; long n; char *result; /* Points to resulting string */ char *ptr; /* Points at the next location we want to copy to */ int result_length; /* Length of resulting string */ if (zend_parse_parameters(argc TSRMLS_CC, "sl", &str, &str_len, &n) == FAILURE) return; /* Calculate length of result */ result_length = (str_len * n); /* Allocate memory for result */ result = (char *) emalloc(result_length + 1); /* Point at the beginning of the result */ ptr = result; while (n--) { /* Copy str to the result */ memcpy(ptr, str, str_len); /* Increment ptr to point at the next position we want to write to */ ptr += str_len; } /* Null terminate the result. Always null-terminate your strings even if they are binary strings */ *ptr = ' '; /* Return result to the scripting engine without duplicating it */ RETURN_STRINGL(result, result_length, 0); } /* }}} */ All you need to do now is to recompile PHP, and you've written your first PHP function. Let's check and see if it really works. Run the following script in your freshly compiled PHP tree: <?php for ($i = 1; $i <= 3; $i++) { print self_concat("ThisIsUseless", $i); print "n"; } ?> You should get the following result: ThisIsUseless ThisIsUselessThisIsUseless ThisIsUselessThisIsUselessThisIsUseless