用C实现PHP扩展类

来源:互联网 发布:手机淘宝首页广告位 编辑:程序博客网 时间:2024/05/16 00:51

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

    准备实现的类如下:

    

class Rectangle{private $_width;private $_height;public function __construct($width, $height){$this->_width = $width;$this->_height = $height;}public function clone(){return new Rectangle($this->_width, $this->_height);}public function setWidth($width){$this->_width = $width;}public function setHeight($height){$this->_height = $height;}public function getWidth(){return $this->_width;}public function getHeight(){return $this->_height;}public function getArea(){return $this->_width * $this->_height;}public function getCircle(){return ($this->_width + $this->_height) * 2;}}


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

1,建立扩展骨架

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

2,修改编译参数

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

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

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

3,编写C代码

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

PHP_METHOD(Rectangle,__construct);PHP_METHOD(Rectangle,clone);PHP_METHOD(Rectangle,setWidth);PHP_METHOD(Rectangle,setHeight);PHP_METHOD(Rectangle,getWidth);PHP_METHOD(Rectangle,getHeight);PHP_METHOD(Rectangle,getArea);PHP_METHDO(Rectangle,getCircle);

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

ZEND_BEGIN_ARG_INFO(arg_construct,2)ZEND_ARG_INFO(0, width)ZEND_ARG_INFO(0, height)ZEND_END_ARG_INFO()ZEND_BEGIN_ARG_INFO(arg_set_width,1)ZEND_ARG_INFO(0, width)ZEND_END_ARG_INFO()ZEND_BEGIN_ARG_INFO(arg_set_height,1)ZEND_ARG_INFO(0, height)ZEND_END_ARG_INFO()const zend_function_entry class_ext_functions[] = {    PHP_FE(confirm_class_ext_compiled, NULL)    PHP_ME(Rectangle, __construct, arg_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, clone, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, setWidth, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, setHeight, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, getWidth, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, getHeight, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, getArea, NULL, ZEND_ACC_PUBLIC)    PHP_ME(Rectangle, getCircle, NULL, ZEND_ACC_PUBLIC)    {NULL, NULL, NULL}  /* Must be the last line in class_ext_functions[] */};
#其中ZEND_ACC_CTOR表示构造函数,ZEND_ACC_PUBLIC表示访问权限为PUBLIC。
#接下来,在模块初始化函数中注册并初始化类

zend_class_entry *Rectangle_ce; //zend内部类结构变量PHP_MINIT_FUNCTION(class_ext){    zend_class_entry Rectangle;    INIT_CLASS_ENTRY(Rectanble, "Rectangle", class_ext_functions); //第二个参数为类名,第三个参数为类的函数列表    Rectangle_ce = zend_register_internal_class_ex(&Rectangle, NULL, NULL TSRMLS_CC); //注册类    zend_declare_property_null(Rectangle_ce, ZEND_STRL("_width"), ZEND_ACC_PRIVATE TSRMLS_CC); //初始化类的属性_width    zend_declare_property_null(Rectangle_ce, ZEND_STRL("_height"), ZEND_ACC_PRIVATE TSRMLS_CC);  //初始化类的属性_height    return SUCCESS;}
#在文件最后增加类的成员函数的具体实现代码
PHP_METHOD(Rectangle, __construct){    long width,height;    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE){ //获取构造函数的两个函数参数_width和_height        WRONG_PARAM_COUNT;    }    if( width <= 0 ) {        width = 1; //如果_width为0,则赋默认值1    }    if( height <= 0 ) {        height = 1; //如果_height为0,则赋默认值1    }    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新类成员变量_width的值    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC);  //更新类成员变量_height的值    RETURN_TRUE;}PHP_METHOD(Rectangle, clone){    zval *clone_obj;    zval *width,*height;    MAKE_STD_ZVAL(clone_obj);    object_init_ex(clone_obj, Rectangle_ce); //初始化对象,对象所属的类为Rectangle_ce    width = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC); //获取类成员变量_width的值    height = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC); //获取类成员变量_height的值    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新Rectangle_ce类对象clone_obj的属性值_width    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //更新Rectangle_ce类对象clone_obj的属性值_height    RETURN_ZVAL(clone_obj, 1, 0);  //返回该对象}PHP_METHOD(Rectangle, setWidth(){    long width;    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &width) == FAILURE){        WRONG_PARAM_COUNT;    }    if( width <= 0 ) {        width = 1;    }    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //更新类成员变量_width的值    RETURN_TRUE;}PHP_METHOD(Rectangle, setHeight(){    long height;    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &height) == FAILURE){        WRONG_PARAM_COUNT;    }    if( height <= 0 ) {        height = 1;    }    zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //更新类成员变量_height的值    RETURN_TRUE;}PHP_METHOD(Rectangle, getWidth){    zval *zWidth;    long width;    zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC); //获取类成员变量_width的值    width = Z_LVAL_P(zWidth);    RETURN_LONG(width);}PHP_METHOD(Rectangle, getHeight){    zval *zHeight;    long height;    zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);    height = Z_LVAL_P(zHeight);    RETURN_LONG(height);}PHP_METHOD(Rectangle, getArea){    zval *zWidth,*zHeight;    long width,height,area;    zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC);    zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);    width = Z_LVAL_P(zWidth);    height = Z_LVAL_P(zHeight);    area = width * height;    RETURN_LONG(area);}PHP_METHOD(Rectangle, getCircle){    zval *zWidth,*zHeight;    long width,height,circle;    zWidth = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC);    zHeight = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);    width = Z_LVAL_P(zWidth);    height = Z_LVAL_P(zHeight);    circle = (width + height) * 2;    RETURN_LONG(circle);}

4,编译代码

cd php-5.2.8/ext/class_ext/usr/local/php/bin/phpize./configure --with-php-config=/usr/local/php/bin/php-configmake 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,测试代码

$width = -10;$height = 12;$rectangle = new Rectangle($width, $height);$area = $rectangle->getArea();var_dump($area);$circle = $rectangle->getCircle();var_dump($circle);$clone = $rectangle->clone();$_area = $clone->getArea();var_dump($_area);$clone->setWidth(100);$clone->setHeight(200);$_area = $clone->getArea();var_dump($_area);$width = $clone->getWidth();var_dump($width);$height = $clone->getHeight();var_dump($height);

结果输出:

int(12)int(26)int(12)int(20000)int(100)int(200)

6,Over!







原创粉丝点击