知识屋:更实用的电脑技术知识网站
所在位置:首页 > 编程技术 > PHP编程

用C实现PHP扩展类的步骤

发布时间:2015-05-27 19:31:22作者:知识屋

   前面简单介绍了用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,建立扩展骨架

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

2,修改编译参数
[php] 
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,修改后为:


[php]
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代码

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

[php] 
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); 

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

[php] 
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[] */ 
}; 
[php] 
#其中ZEND_ACC_CTOR表示构造函数,ZEND_ACC_PUBLIC表示访问权限为PUBLIC。 
[php] 
#接下来,在模块初始化函数中注册并初始化类 

[php] 
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] 
#在文件最后增加类的成员函数的具体实现代码 
[php] 
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,编译代码

[php] 
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,测试代码

[php] 
$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); 

结果输出:
[php] 
int(12) 
int(26) 
int(12) 
int(20000) 
int(100) 
int(200) 

 

 

 

(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)
收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜