Home > Article > Backend Development > Steps to implement PHP extension class in C_PHP tutorial
Previously we briefly introduced the steps to implement PHP extension using C language. See the steps to develop PHP extension using C. That is to extend a function. Here we will explain how to use C to extend a class.
The classes to be implemented are as follows:
[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;
}
}
The steps to implement class extension are as follows: (First download the PHP source code, here we use php-5.2.8)
1. Create an extended skeleton
[php]
cd php-5.2.8/ext
./ext_skel --extname=class_ext
2, modify compilation parameters
[php]
cd php-5.2.8/ext/class_ext
vi config.m4
Remove PHP_ARG_ENABLE(class_ext, whether to enable class_ext support, and
[ --enable-class_ext Enable class_ext support]) The dnl in front of the two lines, modified to:
[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. Write C code
[php]
cd php-5.2.8/ext/class_ext
vi php_class_ext.h
#Add the declaration function after 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
#Declare the parameters of the method and register them in the function table
[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 internal class structure variable
PHP_MINIT_FUNCTION(class_ext)
{
zend_class_entry Rectangle;
INIT_CLASS_ENTRY(Rectanble, "Rectangle", class_ext_functions); //The second parameter is the class name, and the third parameter is the function list of the class
Rectangle_ce = zend_register_internal_class_ex(&Rectangle, NULL, NULL TSRMLS_CC); //Register class
zend_declare_property_null(Rectangle_ce, ZEND_STRL("_width"), ZEND_ACC_PRIVATE TSRMLS_CC); //Initialize the properties of the class _width
zend_declare_property_null(Rectangle_ce, ZEND_STRL("_height"), ZEND_ACC_PRIVATE TSRMLS_CC); //Initialize the properties of the class _height
Return SUCCESS;
}
[php]
#Add the specific implementation code of the class member function at the end of the file
[php]
PHP_METHOD(Rectangle, __construct)
{
long width,height;
If(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &width, &height) == FAILURE){ //Get the two function parameters _width and _height of the constructor
WRONG_PARAM_COUNT;
}
If( width <= 0 ) {
width = 1; //If _width is 0, assign the default value 1
}
If( height <= 0 ) {
height = 1; //If _height is 0, assign the default value 1
}
zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //Update the value of class member variable _width
zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //Update the value of class member variable _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); //Initialize the object, the class to which the object belongs is Rectangle_ce
width = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), 0 TSRMLS_CC); //Get the value of class member variable _width
height = zend_read_property(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), 0 TSRMLS_CC); //Get the value of class member variable _height
zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_width"), width TSRMLS_CC); //Update the attribute value _width of the Rectangle_ce class object clone_obj
zend_update_property_long(Z_OBJCE_P(getThis()), getThis(), ZEND_STRL("_height"), height TSRMLS_CC); //Update the property value _height of the Rectangle_ce class object clone_obj
RETURN_ZVAL(clone_obj, 1, 0); //Return the object
}
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); //Update the value of class member variable _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); //Update the value of class member variable _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)