Chinaunix首页 | 论坛 | 博客
  • 博客访问: 410612
  • 博文数量: 155
  • 博客积分: 2590
  • 博客等级: 少校
  • 技术积分: 2161
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-25 09:33
文章分类

全部博文(155)

文章存档

2015年(1)

2014年(2)

2013年(55)

2012年(97)

分类: C/C++

2012-11-08 09:17:18

前面简单介绍了用C语言实现PHP扩展的步骤,见用C开发PHP扩展的步骤,那个是扩展一个函数,这里讲述一下如何用C扩展类。

    准备实现的类如下:

    

  1. class Rectangle{  
  2.     private $_width;  
  3.     private $_height;  
  4.     public function __construct($width$height){  
  5.         $this->_width = $width;  
  6.         $this->_height = $height;  
  7.     }  
  8.     public function clone(){  
  9.         return new Rectangle($this->_width, $this->_height);  
  10.     }  
  11.     public function setWidth($width){  
  12.         $this->_width = $width;  
  13.     }  
  14.     public function setHeight($height){  
  15.         $this->_height = $height;  
  16.     }  
  17.     public function getWidth(){  
  18.         return $this->_width;  
  19.     }  
  20.     public function getHeight(){  
  21.         return $this->_height;  
  22.     }  
  23.     public function getArea(){  
  24.         return $this->_width * $this->_height;  
  25.     }  
  26.     public function getCircle(){  
  27.         return ($this->_width + $this->_height) * 2;  
  28.     }  
  29. }  

实现类扩展的步骤如下:(首先下载PHP源码,这里使用的是php-5.2.8)

1,建立扩展骨架

  1. cd php-5.2.8/ext  
  2. ./ext_skel --extname=class_ext  

2,修改编译参数

  1. cd php-5.2.8/ext/class_ext  
  2. vi config.m4  
去掉PHP_ARG_ENABLE(class_ext, whether to enable class_ext support,和

[   --enable-class_ext       Enable class_ext support])两行前面的dnl,修改后为:

  1. dnl Otherwise use enable:    
  2. PHP_ARG_ENABLE(class_ext, whether to enable class_ext support,    
  3. dnl Make sure that the comment is aligned:    
  4. [  --enable-class_ext           Enable class_ext support])  

3,编写C代码

  1. cd php-5.2.8/ext/class_ext  
  2. vi php_class_ext.h  
  3. #在 PHP_FUNCTION(confirm_class_ext_compiled); 后面增加申明函数;  

  1. PHP_METHOD(Rectangle,__construct);  
  2. PHP_METHOD(Rectangle,clone);  
  3. PHP_METHOD(Rectangle,setWidth);  
  4. PHP_METHOD(Rectangle,setHeight);  
  5. PHP_METHOD(Rectangle,getWidth);  
  6. PHP_METHOD(Rectangle,getHeight);  
  7. PHP_METHOD(Rectangle,getArea);  
  8. PHP_METHDO(Rectangle,getCircle);  

  1. vi class_ext.c  
  2. #申明方法的参数,注册到函数表中  

  1. ZEND_BEGIN_ARG_INFO(arg_construct,2)  
  2. ZEND_ARG_INFO(0, width)  
  3. ZEND_ARG_INFO(0, height)  
  4. ZEND_END_ARG_INFO()  
  5.   
  6. ZEND_BEGIN_ARG_INFO(arg_set_width,1)  
  7. ZEND_ARG_INFO(0, width)  
  8. ZEND_END_ARG_INFO()  
  9.   
  10. ZEND_BEGIN_ARG_INFO(arg_set_height,1)  
  11. ZEND_ARG_INFO(0, height)  
  12. ZEND_END_ARG_INFO()  
  13.   
  14. const zend_function_entry class_ext_functions[] = {  
  15.     PHP_FE(confirm_class_ext_compiled, NULL)  
  16.     PHP_ME(Rectangle, __construct, arg_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)  
  17.     PHP_ME(Rectangle, clone, NULL, ZEND_ACC_PUBLIC)  
  18.     PHP_ME(Rectangle, setWidth, NULL, ZEND_ACC_PUBLIC)  
  19.     PHP_ME(Rectangle, setHeight, NULL, ZEND_ACC_PUBLIC)  
  20.     PHP_ME(Rectangle, getWidth, NULL, ZEND_ACC_PUBLIC)  
  21.     PHP_ME(Rectangle, getHeight, NULL, ZEND_ACC_PUBLIC)  
  22.     PHP_ME(Rectangle, getArea, NULL, ZEND_ACC_PUBLIC)  
  23.     PHP_ME(Rectangle, getCircle, NULL, ZEND_ACC_PUBLIC)  
  24.     {NULL, NULL, NULL}  /* Must be the last line in class_ext_functions[] */  
  25. };  
  1. #其中ZEND_ACC_CTOR表示构造函数,ZEND_ACC_PUBLIC表示访问权限为PUBLIC。  
  1. #接下来,在模块初始化函数中注册并初始化类  

  1. zend_class_entry *Rectangle_ce; //zend内部类结构变量  
  2. PHP_MINIT_FUNCTION(class_ext)  
  3. {  
  4.     zend_class_entry Rectangle;  
  5.     INIT_CLASS_ENTRY(Rectanble, "Rectangle", class_ext_functions); //第二个参数为类名,第三个参数为类的函数列表  
  6.     Rectangle_ce = zend_register_internal_class_ex(&Rectangle, NULL, NULL TSRMLS_CC); //注册类  
  7.     zend_declare_property_null(Rectangle_ce, ZEND_STRL("_width"), ZEND_ACC_PRIVATE TSRMLS_CC); //初始化类的属性_width  
  8.     zend_declare_property_null(Rectangle_ce, ZEND_STRL("_height"), ZEND_ACC_PRIVATE TSRMLS_CC);  //初始化类的属性_height  
  9.     return SUCCESS;  
  10. }  
  1. #在文件最后增加类的成员函数的具体实现代码  
  1. PHP_METHOD(Rectangle, __construct)  
  2. {  
  3.     long width,height;  
  4.     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE){ //获取构造函数的两个函数参数_width和_height  
  5.         WRONG_PARAM_COUNT;  
  6.     }  
  7.     if( width <= 0 ) {  
  8.         width = 1; //如果_width为0,则赋默认值1  
  9.     }  
  10.     if( height <= 0 ) {  
  11.         height = 1; //如果_height为0,则赋默认值1  
  12.     }  
  13.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新类成员变量_width的值  
  14.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC);  //更新类成员变量_height的值  
  15.     RETURN_TRUE;  
  16. }  
  17.   
  18. PHP_METHOD(Rectangle, clone)  
  19. {  
  20.     zval *clone_obj;  
  21.     zval *width,*height;  
  22.     MAKE_STD_ZVAL(clone_obj);  
  23.     object_init_ex(clone_obj, Rectangle_ce); //初始化对象,对象所属的类为Rectangle_ce  
  24.     width = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC); //获取类成员变量_width的值  
  25.     height = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC); //获取类成员变量_height的值  
  26.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新Rectangle_ce类对象clone_obj的属性值_width  
  27.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //更新Rectangle_ce类对象clone_obj的属性值_height  
  28.     RETURN_ZVAL(clone_obj, 1, 0);  //返回该对象  
  29. }  
  30.   
  31. PHP_METHOD(Rectangle, setWidth()  
  32. {  
  33.     long width;  
  34.     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &width) == FAILURE){  
  35.         WRONG_PARAM_COUNT;  
  36.     }  
  37.     if( width <= 0 ) {  
  38.         width = 1;  
  39.     }  
  40.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新类成员变量_width的值  
  41.     RETURN_TRUE;  
  42. }  
  43.   
  44. PHP_METHOD(Rectangle, setHeight()  
  45. {  
  46.     long height;  
  47.     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &height) == FAILURE){  
  48.         WRONG_PARAM_COUNT;  
  49.     }  
  50.     if( height <= 0 ) {  
  51.         height = 1;  
  52.     }  
  53.     zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //更新类成员变量_height的值  
  54.     RETURN_TRUE;  
  55. }  
  56.   
  57. PHP_METHOD(Rectangle, getWidth)  
  58. {  
  59.     zval *zWidth;  
  60.     long width;  
  61.     zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC); //获取类成员变量_width的值  
  62.     width = Z_LVAL_P(zWidth);  
  63.     RETURN_LONG(width);  
  64. }  
  65.   
  66. PHP_METHOD(Rectangle, getHeight)  
  67. {  
  68.     zval *zHeight;  
  69.     long height;  
  70.     zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);  
  71.     height = Z_LVAL_P(zHeight);  
  72.     RETURN_LONG(height);  
  73. }  
  74.   
  75. PHP_METHOD(Rectangle, getArea)  
  76. {  
  77.     zval *zWidth,*zHeight;  
  78.     long width,height,area;  
  79.     zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC);  
  80.     zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);  
  81.     width = Z_LVAL_P(zWidth);  
  82.     height = Z_LVAL_P(zHeight);  
  83.     area = width * height;  
  84.     RETURN_LONG(area);  
  85. }  
  86.   
  87. PHP_METHOD(Rectangle, getCircle)  
  88. {  
  89.     zval *zWidth,*zHeight;  
  90.     long width,height,circle;  
  91.     zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC);  
  92.     zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);  
  93.     width = Z_LVAL_P(zWidth);  
  94.     height = Z_LVAL_P(zHeight);  
  95.     circle = (width + height) * 2;  
  96.     RETURN_LONG(circle);  
  97. }  

4,编译代码

  1. cd php-5.2.8/ext/class_ext  
  2. /usr/local/php/bin/phpize  
  3. ./configure --with-php-config=/usr/local/php/bin/php-config  
  4. make   
  5. make install  

此时会在php的安装路径下产生一个so文件,比如

/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/class_ext.so

修改php.ini 添加扩展extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/"
[class_ext]
extension = class_ext.so

5,测试代码

  1. $width = -10;  
  2. $height = 12;  
  3. $rectangle = new Rectangle($width$height);  
  4. $area = $rectangle->getArea();  
  5. var_dump($area);  
  6. $circle = $rectangle->getCircle();  
  7. var_dump($circle);  
  8. $clone = $rectangle->clone();  
  9. $_area = $clone->getArea();  
  10. var_dump($_area);  
  11. $clone->setWidth(100);  
  12. $clone->setHeight(200);  
  13. $_area = $clone->getArea();  
  14. var_dump($_area);  
  15. $width = $clone->getWidth();  
  16. var_dump($width);  
  17. $height = $clone->getHeight();  
  18. var_dump($height);  

结果输出:

  1. int(12)  
  2. int(26)  
  3. int(12)  
  4. int(20000)  
  5. int(100)  
  6. int(200)  
  7. 原文:
阅读(1173) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

wzx198404232016-10-24 17:53:37

private $_width;  
private $_height;

请问下如果这两个变量设置为public,如何实现在扩展的构造函数里赋值,并且在php里通过echo输出变量呢?