前面简单介绍了用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,建立扩展骨架
- 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}
- };
- #其中ZEND_ACC_CTOR表示构造函数,ZEND_ACC_PUBLIC表示访问权限为PUBLIC。
- zend_class_entry *Rectangle_ce;
- 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);
- zend_declare_property_null(Rectangle_ce, ZEND_STRL("_height"), ZEND_ACC_PRIVATE TSRMLS_CC);
- return SUCCESS;
- }
- PHP_METHOD(Rectangle, __construct)
- {
- long width,height;
- if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE){
- WRONG_PARAM_COUNT;
- }
- if( width <= 0 ) {
- width = 1;
- }
- if( height <= 0 ) {
- height = 1;
- }
- zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC);
- zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC);
- RETURN_TRUE;
- }
-
- PHP_METHOD(Rectangle, clone)
- {
- zval *clone_obj;
- zval *width,*height;
- MAKE_STD_ZVAL(clone_obj);
- object_init_ex(clone_obj, Rectangle_ce);
- width = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC);
- height = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC);
- zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC);
- zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC);
- 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);
- 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);
- 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 = 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)
- 原文:
阅读(1224) | 评论(1) | 转发(0) |