用C兑现PHP扩展类

php中文网
发布: 2016-06-13 13:05:37
原创
905人浏览过

用C实现PHP扩展类

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

    准备实现的类如下:

    

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,建立扩展骨架

立即学习PHP免费学习笔记(深入)”;

cd php-5.2.8/ext
./ext_skel --extname=class_ext
登录后复制

2,修改编译参数

cd php-5.2.8/ext/class_ext
vi 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_ext
vi 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-config
make 
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!







PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号