|
| 1 | +# 在扩展中使用函数 |
| 2 | + |
| 3 | +我们在 hello-world 扩展的例子中,通过原型框架生成了一个简单的函数,修改之后如下 |
| 4 | + |
| 5 | + [c] |
| 6 | + /* {{{ proto string tipi_hello_world(string name) |
| 7 | + */ |
| 8 | + PHP_FUNCTION(tipi_hello_world) |
| 9 | + { |
| 10 | + char *name = NULL; |
| 11 | + int argc = ZEND_NUM_ARGS(); |
| 12 | + size_t name_len; |
| 13 | + |
| 14 | + char *result = NULL; |
| 15 | + char *prefix = "hello world, "; |
| 16 | + |
| 17 | + #ifndef FAST_ZPP |
| 18 | + if (zend_parse_parameters(argc TSRMLS_CC, "s", &name, &name_len) == FAILURE) |
| 19 | + return; |
| 20 | + #else |
| 21 | + ZEND_PARSE_PARAMETERS_START(1, 1) |
| 22 | + Z_PARAM_STRING(name, name_len) |
| 23 | + ZEND_PARSE_PARAMETERS_END(); |
| 24 | + #endif |
| 25 | + |
| 26 | + result = (char *) ecalloc(strlen(prefix) + name_len + 1, sizeof(char)); |
| 27 | + strncat(result, prefix, strlen(prefix)); |
| 28 | + strncat(result, name, name_len); |
| 29 | + |
| 30 | + RETURN_STRING(result); |
| 31 | + } |
| 32 | + /* }}} */ |
| 33 | + |
| 34 | +## PHP_FUNCTION 宏 |
| 35 | + |
| 36 | +在 PHP 扩展中,所有的函数均以 `PHP_FUNCTION(extension_name){...}`的结构来表示, |
| 37 | + |
| 38 | + [c] |
| 39 | + /* main/php.h */ |
| 40 | + #define PHP_FUNCTION ZEND_FUNCTION |
| 41 | + /* Zend/zend_API.h */ |
| 42 | + #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) |
| 43 | + |
| 44 | + #define ZEND_FN(name) zif_##name |
| 45 | + #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) |
| 46 | + |
| 47 | + #define INTERNAL_FUNCTION_PARAMETERS zend_execute_data *execute_data, zval *return_value |
| 48 | + |
| 49 | +相对 PHP5 中 `INTERNAL_FUNCTION_PARAMETERS` 宏表示的参数简单了很多。 |
| 50 | +在上例中 `return_value` 虽然没有显性地使用,实际通过 `RETURN_STRING` 隐形地使用了。 |
| 51 | + |
| 52 | +## 从函数中返回 |
| 53 | + |
| 54 | +扩展API包含丰富的用于从函数中返回值的宏。这些宏有两种主要风格:第一种是 `RETVAL_type()` 形式,它设置了返回值但C代码继续执行。 |
| 55 | +这通常使用在把控制交给脚本引擎前还希望做的一些清理工作的时候使用,然后再使用C的返回声明 `return` 返回到 PHP; |
| 56 | +后一个宏更加普遍,其形式是 `RETURN_type()`,他设置了返回类型,同时返回控制到 PHP。 |
| 57 | + |
| 58 | + [c] |
| 59 | + /* Zend/zend_API.h */ |
| 60 | + #define RETURN_BOOL(b) { RETVAL_BOOL(b); return; } |
| 61 | + #define RETURN_NULL() { RETVAL_NULL(); return;} |
| 62 | + #define RETURN_LONG(l) { RETVAL_LONG(l); return; } |
| 63 | + #define RETURN_DOUBLE(d) { RETVAL_DOUBLE(d); return; } |
| 64 | + #define RETURN_STR(s) { RETVAL_STR(s); return; } |
| 65 | + #define RETURN_INTERNED_STR(s) { RETVAL_INTERNED_STR(s); return; } |
| 66 | + #define RETURN_NEW_STR(s) { RETVAL_NEW_STR(s); return; } |
| 67 | + #define RETURN_STR_COPY(s) { RETVAL_STR_COPY(s); return; } |
| 68 | + #define RETURN_STRING(s) { RETVAL_STRING(s); return; } |
| 69 | + #define RETURN_STRINGL(s, l) { RETVAL_STRINGL(s, l); return; } |
| 70 | + #define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; } |
| 71 | + #define RETURN_RES(r) { RETVAL_RES(r); return; } |
| 72 | + #define RETURN_ARR(r) { RETVAL_ARR(r); return; } |
| 73 | + #define RETURN_OBJ(r) { RETVAL_OBJ(r); return; } |
| 74 | + #define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } |
| 75 | + #define RETURN_FALSE { RETVAL_FALSE; return; } |
| 76 | + #define RETURN_TRUE { RETVAL_TRUE; return; } |
| 77 | + |
| 78 | +以 `RETURN_STRING` 为例 |
| 79 | + |
| 80 | + [c] |
| 81 | + #define RETURN_STR(s) { RETVAL_STR(s); return; } |
| 82 | + |
| 83 | + #define RETVAL_STR(s) ZVAL_STR(return_value, s) |
| 84 | + |
| 85 | +实际是将 `s` 赋值给 `return_value`,详细代码读者可以自己在源码中跟下。 |
| 86 | + |
| 87 | +与 `PHP_FUNCTION` 宏类似, `PHP_METHOD` 用来封装类中的方法。 |
0 commit comments