周梦康 发表于 2016-02-27 8370 次浏览 标签 : PHP 扩展开发

PHP 扩展开发的文章,我均已更新至《TIPI》(下面的博文可能已经过时,以 TIPI 上的内容为准)。

例如上篇中的

PHP_FUNCTION(confirm_helloworld_compiled)
{
	char *arg = NULL;
	size_t arg_len, len;
	zend_string *strg;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
		return;
	}

	strg = strpprintf(0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "helloworld", arg);

	RETURN_STR(strg);
}

ZEND_NUM_ARGS() 获取参数个数的宏

Zend/zend_API.h
#define ZEND_NUM_ARGS()						EX_NUM_ARGS()

zend_parse_parameters解析参数,第一个参数是传递给函数的参数个数。通常的做法是传给它ZEND_NUM_ARGS()。第二个参数是一个字符串,指定了函数期望的参数类型,后面紧跟着需要随参数值更新的变量列表。因为PHP采用松散的变量定义和动态的类型判断,这样做就使得把不同类型的参数转化为期望的类型成为可能。

ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...)

下表列出了可能指定的类型。

类型指定符对应的C类型描述
llong符号整数
ddouble浮点数
schar *, int二进制字符串,长度
bzend_bool逻辑型(1或0)
rzval *资源(文件指针,数据库连接等)
azval *联合数组
ozval *任何类型的对象
Ozval *指定类型的对象。需要提供目标对象的类类型
zzval *无任何操作的zval

例如下面该表达式则是获取两个参数strn,字符串的类型是s,需要两个参数char *字符串和int长度;数字的类型l,只需要一个参数

zend_parse_parameters(argc TSRMLS_CC, "sl", &str, &str_len, &n)

可变参数的原理

看其源码

ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* {{{ */
{
   va_list va;
   int retval;
   int flags = 0;

   va_start(va, type_spec);
   retval = zend_parse_va_args(num_args, type_spec, &va, flags);
   va_end(va);

   return retval;
}

主要使用到了va_list,va_start,va_argva_end来获取可变个数的参数。

写了个代码片段,加深印象

#include <stdarg.h>
#include <stdio.h>

int zend_parse_parameters(int num_args, ...);

int zend_parse_parameters2(int num_args, const char *type_spec, ...);

int main() {

    zend_parse_parameters(3, 1, 2, 3);
    zend_parse_parameters2(4, "abcd", 1, 2, 3, 4);
    return 0;
}

int zend_parse_parameters(int num_args, ...) {
    va_list va;

    va_start(va, num_args);
    for (int i = 0; i < num_args; ++i) {
        printf("第 %d 个参数为: %d\n", i, va_arg(va, int));
    }
    va_end(va);

    printf("===============\n");
    return 0;
}

int zend_parse_parameters2(int num_args, const char *type_spec, ...) {
    va_list va;
    const char *spec_walk;
    char c;

    va_start(va, type_spec);
    for (spec_walk = type_spec; *spec_walk; spec_walk++) {
        c = *spec_walk;
        printf("参数类型为 %c 值为: %d\n", c, va_arg(va, int));
    }
    va_end(va);

    printf("===============\n");
    return 0;
}

输出结果

第 0 个参数为: 1
第 1 个参数为: 2
第 2 个参数为: 3
===============
参数类型为 a 值为: 1
参数类型为 b 值为: 2
参数类型为 c 值为: 3
参数类型为 d 值为: 4
==================


评论列表