原文: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), self, ZEND_STRL("_name"), 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, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
PHP_ME(Person, __destruct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
PHP_ME(Person, getName, NULL, ZEND_ACC_PUBLIC)
PHP_ME(Person, setName, arg_person_setname, ZEND_ACC_PUBLIC)
{NULL, 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.

用扩展开发一个PHP类的更多相关文章

  1. 用Java开发一个工具类,提供似于js中eval函数功能的eval方法

    今天在看到<Java疯狂讲义>中一个章节习题: 开发一个工具类,该工具类提供一个eval()方法,实现JavaScript中eval()函数的功能--可以动态运行一行或多行程序代码.例如: ...

  2. 【Android开发VR实战】三.开发一个寻宝类VR游戏TreasureHunt

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53939303 本文出自[DylanAndroid的博客] [Android开发 ...

  3. php扩展开发3--扩展类传参数

    1.需要实现的细节 实现一个person类 ,实现一个doing方法和saying方法 在构造方法中传递一个数组,在doing中打印此数组 saying方法中,构建一个空数组,返回,不需要传参. 2. ...

  4. php扩展开发2--添加类

    1.需要实现的细节 实现一个person类 实现一个doing方法和saying方法 2.第一个扩展 2.1创建类的扩展: [root@bogon ext]# cd /usr/local/src/ph ...

  5. PHP扩展开发(4) - 多类扩展

    由于函数和单类的扩展,网上一搜一大片,这里就不再叙述了. 这里特别感谢laruence(鸟哥)开源的yaf扩展,解决困扰我多时的多类问题,还在看他的代码学习中,这里是对多类写法学习的一个阶段总结.   ...

  6. PHP扩展开发之简单类开发

    接下来我们要用扩展的形式实现以下类(演示环境:linux.php-5.5.34-src) <?php class Person { private $_name; public function ...

  7. 行内人解读开发一个App需要多少钱?

    对于很多互联网的创业者来说,评估前期的创业成本是很重要的.在这几年的创业大潮中,伴随着“互联网+”和“互联网思维”的普及,很多创业项目选择了开发app作为创业项目的载体.在我接触到的很多创业者,找Ap ...

  8. 如何使用Add-on SDK开发一个自己的火狐扩展

    黄聪:如何使用Add-on SDK开发一个自己的火狐扩展 火狐开放了扩展的开发权限给程序员们,相信很多人都会希望自己做一些扩展来方便一些使用. 我最近做一些项目也需要开发一个火狐扩展,方便收集自己需要 ...

  9. 如何用原生js开发一个Chrome扩展程序

    原文地址:How to Build a Simple Chrome Extension in Vanilla JavaScript 开发一个Chrome扩展程序非常简单,只需要使用原生的js就可以完成 ...

随机推荐

  1. Chrome一直提示“adobe flash player 因过期而遭阻止” ,如何解决?

    完全不用安装最新版的 Chrome,只需要将 Flash 组件安装一下最新版即可. 并且这里需要的不是网上随处可见的 NPAPI 版本,而是冷门的 PPAPI 版本. 请收藏好这个链接,是某位大牛从 ...

  2. TDD测试驱动开发

    TDD测试驱动开发 一.概念 TDD故名思意就是用测试的方法驱动开发,简单说就是先写测试代码,再写开发代码.传统的方式是先写代码,再测试,它的开发方式与之正好相反. TDD是极限编程的一个最重要的设计 ...

  3. 深度学习框架搭建之最新版Python及最新版numpy安装

    这两天为了搭载深度学习的Python架构花了不少功夫,但是Theano对Python以及nunpy的版本都有限制,所以只能选用版本较新的python和nunpy以确保不过时.但是最新版Python和最 ...

  4. 【BFS】POJ 3414

    直达 -> POJ 3414 Pots 相似题联动–>HDU 1495 非常可乐 题意:两个壶倒水,三种操作,两个桶其中一个满足等于C的最少操作,输出路径.注意a,b互倒的时候能不能倒满, ...

  5. Axure的学习

    这两天开始学习Axure,首先做的是下载Axure的7.0版本,然后汉化,可以百度找.不过我在开始学习时也遇到一些问题.在开始添加元件库时还是很顺利的,不过在我发布的时候,我发现了一些问题.发布一开始 ...

  6. linux 字符设备驱动写法

    字符设备,块设备书 一.register_chrdev_region, register_chrdev, misc_register misc device(杂项设备) 在 Linux 内核的incl ...

  7. 国内外三个不同领域巨头分享的Redis实战经验及使用场景

    Redis不是比较成熟的memcache或者Mysql的替代品,是对于大型互联网类应用在架构上很好的补充.现在有越来越多的应用也在纷纷基于Redis做架构的改造.首先简单公布一下Redis平台实际情况 ...

  8. java基础知识小总结【转】

    java基础知识小总结 在一个独立的原始程序里,只能有一个 public 类,却可以有许多 non-public 类.此外,若是在一个 Java 程序中没有一个类是 public,那么该 Java 程 ...

  9. TortoiseSVN 合并操作简明教程

    下列步骤展示了如何将分支A中的修改合并到分支B. 1.在分支B的本地副本目录中选择"合并(Merge)". 2.选择“合并一个版本范围(Merge a range of revis ...

  10. Python操作Mysql数据库时SQL语句的格式问题

    一.概述 近日使用Python对Mysql数据库进行操作,遇到SQL语句死活出问题的情况.由于最初没有将异常打印出来,一直不知道原因.随后,将异常打印出来之后,通过异常信息,对代码进行修改.最终,成功 ...