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 = ‘\0′;
/* 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
