PHP擴展開發之簡單類開發

接下來咱們要用擴展的形式實現如下類(演示環境:linux、php-5.5.34-src)php

 1 <?php 
 2 class Person
 3 {
 4     private $_name;
 5     public function getName()
 6     {
 7         return $this -> _name;
 8     } 
 9     public function setName($name)
10     {
11         $this -> _name = $name;
12     } 
13 } 

在PHP源碼目錄下linux

1 cd php-5.5.34-src
2 cd ext
3 ./ext_skel --extname=hdx  //生成hdx擴展骨架
4 cd hdx

1.修改config.m4函數

PHP_ARG_WITH(hdx, for hdx support,    
[  --with-hdx             Include hdx support])

//把這兩行前面的dnl去掉  大概在 10-12行

2.在hdx.h添加以下測試

PHP_METHOD(Person, __construct);
PHP_METHOD(Person, __destruct);
PHP_METHOD(Person, getName);
PHP_METHOD(Person, setName);

3.在hdx.c下方添加相應函數this

 1 PHP_METHOD(Person, __construct) {
 2  php_printf("__construct called.");
 3 }
 4 
 5 PHP_METHOD(Person, __destruct) {
 6  php_printf("__destruct called.<br/>");
 7 }
 8 
 9 PHP_METHOD(Person, getName) {
10  zval *self, *name;
11  self = getThis();
12  name = zend_read_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), 0 TSRMLS_CC);
13  RETURN_STRING(Z_STRVAL_P(name), 0);
14 }
15 
16 PHP_METHOD(Person, setName) {
17  char *arg = NULL;
18  int arg_len;
19  zval *value, *self;
20  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
21  WRONG_PARAM_COUNT;
22  }
23  self = getThis();
24  MAKE_STD_ZVAL(value);
25  ZVAL_STRINGL(value, arg, arg_len, 0);
26  SEPARATE_ZVAL_TO_MAKE_IS_REF(&value);
27  zend_update_property(Z_OBJCE_P(self), self, ZEND_STRL("_name"), value TSRMLS_CC);
28  RETURN_TRUE;
29 }

對上面的代碼作一些解釋:spa

A. 獲取方法的參數信息,仍然使用zend_parse_parameters函數,與以前咱們介紹過的同樣;指針

B. 獲取this指針(相對於PHP代碼而言,在PHP擴展中仍然使用zval結構表示)使用getThis()函數;code

C. 使用MAKE_STD_ZVAL宏申請並初始化一個zval結構,在PHP擴展中,全部的數據類型其實都是用zval結構來表示的,在本系列文章中我會單獨寫一篇來介紹zval。blog

D. 獲取屬性值使用zend_read_property()函數,使用zend_update_property()函數更新屬性值。get

4.在hdx.c 上方,初始化類:在擴展初始化函數中,註冊並初始化類。

1 zend_class_entry *person_ce;
2 
3 PHP_MINIT_FUNCTION(fetion_echo)
4 { 
5     zend_class_entry person; 
INIT_CLASS_ENTRY(person, "Person", fetion_echo_functions); 6 person_ce = zend_register_internal_class_ex(&person, NULL, NULL TSRMLS_CC); 7 8 zend_declare_property_null(person_ce, ZEND_STRL("_name"), ZEND_ACC_PRIVATE TSRMLS_CC); return SUCCESS; 9 }

使用INIT_CLASS_ENTRY宏初始化類,第二個參數指定類名,第三個參數是函數表。

5. 註冊到函數:聲明方法的參數,並註冊到函數表中。

1 ZEND_BEGIN_ARG_INFO(arg_person_setname, 0)
2     ZEND_ARG_INFO(0, name)
3 ZEND_END_ARG_INFO() const zend_function_entry fetion_echo_functions[] = {
4     PHP_ME(Person, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
5     PHP_ME(Person, __destruct,  NULL, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
6     PHP_ME(Person, getName,     NULL, ZEND_ACC_PUBLIC)
7     PHP_ME(Person, setName,     arg_person_setname, ZEND_ACC_PUBLIC)
8     {NULL, NULL, NULL} /* Must be the last line in fetion_echo_functions[] */ };

類方法參數的聲明與以前咱們函數參數聲明方式一致,在註冊類方法到函數表中時使用PHP_ME宏,而不是以前使用的PHP_FE宏。

ZEND_ACC_PUBLIC:指定方法的訪問修飾符

ZEND_ACC_CTOR:指定該方法爲構造函數

ZEND_ACC_DTOR:指定該方法爲析構函數

6.安裝

1 /usr/local/php/bin/phpize
2 ./configure --with-php-config=/usr/local/php/bin/php-config
3 make && make install

而後在PHP安裝目錄下修改php.ini把擴展添加上

7. 運行測試:編譯安裝擴展後,編寫一段簡單的測試腳本:

1 <?php 
2 $person = new Person();
3 $person->setName("huangdongxi"); 
4 echo $person->getName().'<br/>';

運行後能夠看到以下輸出,說明擴展工做正常:__construct called.huangdongxi__destruct called.

相關文章
相關標籤/搜索