• PHP扩展开发之简单类开发


    接下来我们要用扩展的形式实现以下类(演示环境:linux、php-5.5.34-src)

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

    在PHP源码目录下

    1 cd php-5.5.34-src
    2 cd ext
    3 ./ext_skel --extname=hdx  //生成hdx扩展骨架
    4 cd hdx

    1.修改config.m4

    PHP_ARG_WITH(hdx, for hdx support,    
    [  --with-hdx             Include hdx support])
    
    //把这两行前面的dnl去掉  大概在 10-12行

    2.在hdx.h添加如下

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

    3.在hdx.c下方添加相应函数

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

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

    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()函数更新属性值。

    4.在hdx.c 上方,初始化类:在扩展初始化函数中,注册并初始化类。

    1 zend_class_entry *person_ce;
    2 
    3 PHP_MINIT_FUNCTION(fetion_echo)
    4 { 
    5     zend_class_entry person; 
    INIT_CLASS_ENTRY(person, "Person", fetion_echo_functions); 6 person_ce = zend_register_internal_class_ex(&person, NULL, NULL TSRMLS_CC); 7 8 zend_declare_property_null(person_ce, ZEND_STRL("_name"), ZEND_ACC_PRIVATE TSRMLS_CC); return SUCCESS; 9 }

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

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

    1 ZEND_BEGIN_ARG_INFO(arg_person_setname, 0)
    2     ZEND_ARG_INFO(0, name)
    3 ZEND_END_ARG_INFO() const zend_function_entry fetion_echo_functions[] = {
    4     PHP_ME(Person, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
    5     PHP_ME(Person, __destruct,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
    6     PHP_ME(Person, getName,     NULL, ZEND_ACC_PUBLIC)
    7     PHP_ME(Person, setName,     arg_person_setname, ZEND_ACC_PUBLIC)
    8     {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:指定该方法为析构函数

    6.安装

    1 /usr/local/php/bin/phpize
    2 ./configure --with-php-config=/usr/local/php/bin/php-config
    3 make && make install

    然后在PHP安装目录下修改php.ini把扩展添加上

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

    1 <?php 
    2 $person = new Person();
    3 $person->setName("huangdongxi"); 
    4 echo $person->getName().'<br/>';

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

  • 相关阅读:
    邮件收件与草稿箱sql
    [转]全局变量与全局静态变量的区别:
    工作:8月份6-14号的工作初级经验(零碎) 关于传值id经常犯的错误
    网络婚礼之AFNetWorking3.0
    网络热恋之NSURLSession
    网络热恋之json解析
    网络热恋之SDWebImage
    网络热恋之XML解析
    网络&热恋NSURLConnection代理及GET¥POST请求
    网络邂逅&网络异步请求
  • 原文地址:https://www.cnblogs.com/guaidaodark/p/5746313.html
Copyright © 2020-2023  润新知