《PHP扩展开发》--return_value的使用
在PHP扩展中编写函数的时候,如果我们要从PHP扩展返回值给PHP脚本,可以使用return_value
来做到。例如:
1 2 3
| PHP_FUNCTION(hello_world) { ZVAL_STRINGL(return_value, "hello world!", strlen("hello world!")); };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #define ZVAL_STRINGL(z, s, l) do { \ ZVAL_NEW_STR(z, zend_string_init(s, l, 0)); \ } while (0)
static zend_always_inline zend_string *zend_string_init(const char *str, size_t len, int persistent) { zend_string *ret = zend_string_alloc(len, persistent);
memcpy(ZSTR_VAL(ret), str, len); ZSTR_VAL(ret)[len] = '\0'; return ret; }
#define ZSTR_VAL(zstr) (zstr)->val
#define ZVAL_NEW_STR(z, s) do { \ zval *__z = (z); \ zend_string *__s = (s); \ Z_STR_P(__z) = __s; \ Z_TYPE_INFO_P(__z) = IS_STRING_EX; \ } while (0)
|
其中,zend_string_init
的作用就是从堆中分配一块内存给ret
。然后把字符串hello world!
以及字符串的长度保存在ret
里面,然后,返回包含hello world!
字符串的地址。
ZVAL_NEW_STR(z, s)
的作用是让z
指向s
,也就是说,此时的return_value
里面的value.str
指向了zend_string_init
返回的包含了hello world!
字符串的zend_string
。
所以说,通过return_value
可以找到字符串hello world!
。
一个问题是这个return_value
是哪里来的?
我们展开PHP_FUNCTION
可以看到:
1 2 3 4 5
| #define PHP_FUNCTION ZEND_FUNCTION #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) #define ZEND_FN(name) zif_##name #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) #define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value
|
因此,我们对PHP_FUNCTION(hello_world)
进行展开的话,可以得到:
1
| zif_hello_world(zend_execute_data *execute_data, zval *return_value)
|
所以,我们可以在使用了PHP_FUNCTION
宏里面使用return_value
。我们往return_value
里面填充值的话,PHP
脚本就可以得到返回值了。
因此,我们执行如下脚本:
1 2 3 4
| <?php
$ret = hello_world(); var_dump($ret);
|
就可以打印出:
1 2
| ~/codeDir/phpCode/test # php study.php string(12) "hello world!"
|