加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

用扩展开发一个PHP类

发布时间:2020-12-13 21:23:07 所属栏目:PHP教程 来源:网络整理
导读:原文:http://my.oschina.net/mickelfeng/blog/122519?p=1 假设我们要用PHP扩展实 现一个类Person,它有一个private的成员变量$_name和两个public的实例方法getName()和setName(),可以用 PHP代码表示如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 ?php class Person

原文:http://my.oschina.net/mickelfeng/blog/122519?p=1

假设我们要用PHP扩展实 现一个类Person,它有一个private的成员变量$_name和两个public的实例方法getName()和setName(),可以用 PHP代码表示如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
<?php class Person
{
??? private $_name;
??? public function getName()
??? {
??? ? ? return $this -> _name;
??? }?
??? public function setName($name)
??? {
??? ? ? $this -> _name = $name;
??? }?
}?

1. 声明方法:还使用第一篇文章里面用过的示例,首先在头文件php_fetion_echo.h里加入方法声明。

PHP_METHOD(Person,__construct);
PHP_METHOD(Person,__destruct);
PHP_METHOD(Person,getName);
PHP_METHOD(Person,setName);

前面的扩展在声明函数时使用PHP_FUNCTION宏,而在实现类扩展时我们使用PHP_METHOD宏,第一个参数指定类名,第二个参数指定方法名。

2. 方法实现:在fetion_echo.c文件中实现这几个方法,构造函数和析构函数中只是输出一些文本。

?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
PHP_METHOD(Person,__construct) {
?php_printf("__construct called.");
}
?
PHP_METHOD(Person,__destruct) {
?php_printf("__destruct called.<br/>");
}
?
PHP_METHOD(Person,getName) {
?zval *self,*name;
?self = getThis();
?name = zend_read_property(Z_OBJCE_P(self),self,ZEND_STRL("_name"),0 TSRMLS_CC);
?RETURN_STRING(Z_STRVAL_P(name),0);
}
?
PHP_METHOD(Person,setName) {
?char *arg = NULL;
?int arg_len;
?zval *value,*self;
?if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",&arg,&arg_len) == FAILURE) {
?WRONG_PARAM_COUNT;
?}
?self = getThis();
?MAKE_STD_ZVAL(value);
?ZVAL_STRINGL(value,arg,arg_len,0);
?SEPARATE_ZVAL_TO_MAKE_IS_REF(&value);
?zend_update_property(Z_OBJCE_P(self),value TSRMLS_CC);
?RETURN_TRUE;
}

对上面的代码做一些解释:

A. 获取方法的参数信息,仍然使用zend_parse_parameters函数,与之前我们介绍过的一样;

B. 获取this指针(相对于PHP代码而言,在PHP扩展中仍然使用zval结构表示)使用getThis()函数;

C. 使用MAKE_STD_ZVAL宏申请并初始化一个zval结构,在PHP扩展中,所有的数据类型其实都是用zval结构来表示的,在本系列文章中我会单独写一篇来介绍zval。

D. 获取属性值使用zend_read_property()函数,使用zend_update_property()函数更新属性值。

3. 初始化类:在扩展初始化函数中,注册并初始化类。

zend_class_entry *person_ce;

PHP_MINIT_FUNCTION(fetion_echo)
{ 
    zend_class_entry person; INIT_CLASS_ENTRY(person,"Person",fetion_echo_functions);
    person_ce = zend_register_internal_class_ex(&person,NULL,NULL TSRMLS_CC);

    zend_declare_property_null(person_ce,ZEND_STRL("_name"),ZEND_ACC_PRIVATE TSRMLS_CC); return SUCCESS;
}

使用INIT_CLASS_ENTRY宏初始化类,第二个参数指定类名,第三个参数是函数表。

4. 注册到函数:声明方法的参数,并注册到函数表中。

ZEND_BEGIN_ARG_INFO(arg_person_setname,0)
    ZEND_ARG_INFO(0,name)
ZEND_END_ARG_INFO() const zend_function_entry fetion_echo_functions[] = {
    PHP_ME(Person,__construct,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
    PHP_ME(Person,__destruct,ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
    PHP_ME(Person,getName,ZEND_ACC_PUBLIC)
    PHP_ME(Person,setName,arg_person_setname,ZEND_ACC_PUBLIC)
    {NULL,NULL} /* Must be the last line in fetion_echo_functions[] */ };

类方法参数的声明与之前我们函数参数声明方式一致,在注册类方法到函数表中时使用PHP_ME宏,而不是之前使用的PHP_FE宏。

ZEND_ACC_PUBLIC:指定方法的访问修饰符

ZEND_ACC_CTOR:指定该方法为构造函数

ZEND_ACC_DTOR:指定该方法为析构函数

5. 运行测试:编译安装扩展后,编写一段简单的测试脚本:

<?php $person = new Person();
    $person->setName("mickelfeng"); echo $person->getName().'<br/>';

运行后可以看到如下输出,说明扩展工作正常:

__construct called.
mickelfeng
__destruct called.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读