PHP擴充開發(7):zval結構

來源:互聯網
上載者:User

轉載自:http://terrylee.me/blog/post/2011/02/12/php-extension-part1.aspx

 

在前面的文章多次提到了zval結構,其實所有使用者定義的變數在PHP中都是用zval類型來表示的,當我門
使用zend_parse_parameters函數解析參數時,Zend引擎會根據相應的資料類型進行類型轉換,而由於PHP中的數組、對象和資源類
型,在C語言中沒有對應的類型,所以無法進行類型轉換,它們都使用zval表示,先看一下zval結構定義:

typedef pval zval;typedef struct _zval_struct zval;struct _zval_struct {    /* Variable information */    zvalue_value value; /* value */    unsigned char type; /* active type */    unsigned char is_ref;    short refcount;};

zval結構的定義使用了C語言中的等位型別,各個欄位說明如下:

value    變數內容的聯合,參見“表3.6 Zend zvalue_value 結構”
type    變數的類型。“表3.7 Zend 變數類型”給出了一個完整的變數類型列表
is_ref    0 表示這個變數還不是一個引用。1 表示這個變數還有被別的變數所引用
refcount    表示這個變數是否仍然有效。每增加一個對這個變數的引用,這個數值就增加 1。反之,每失去一個對這個變數的引用,該值就會減1。當引用計數減為0的時候,就說明已經不存在對這個變數的引用了,於是這個變數就會自動釋放

變數類型定義:
IS_NULL    表示是一個空值 NULL
IS_LONG    是一個(長)整數
IS_DOUBLE    是一個雙精確度的浮點數
IS_STRING    是一個字串
IS_ARRAY    是一個數組
IS_OBJECT    是一個對象
IS_BOOL    是一個布爾值
IS_RESOURCE    是一個資源(關於資源的討論,我們以後會在適當的時候討論到它)
IS_STRING    是一個常量

zvalue_value結構定義:

typedef union _zvalue_value {    long lval; /* long value */    double dval; /* double value */    struct {        char *val;        int len;    } str;    HashTable *ht; /* hash table value */    struct {        zend_class_entry *ce;        HashTable *properties;    } obj;} zvalue_value;

zvalue_value結構的說明如下:

lval    如果變數類型為 IS_LONG、IS_BOOLEAN 或 IS_RESOURCE 就用這個屬性值
dval    如果變數類型為 IS_DOUBLE 就用這個屬性值
str    如果變數類型為 IS_STRING 就訪問這個屬性值。它的欄位 len 表示這個字串的長度,欄位 val 則指向該字串。由於 Zend 使用的是 C 風格的字串,因此字串的長度就必須把字串末尾的結束符 0×00 也計算在內
ht    如果變數類型為數組,那這個 ht 就指向數組的雜湊表入口
obj    如果變數類型為 IS_OBJECT 就用這個屬性值

給定一個具體的zval,可用三個便利的宏中的一個測試它的類型:Z_TYPE(zval)、Z_TYPE_P(zval*)或Z_TYPE_PP(zval**)。三者之間僅有的功能上的區別在於傳入的變數所期望的間接的層級。如下面的樣本:

PHP_FUNCTION(hello_dump){    zval *uservar;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",     &uservar) == FAILURE) {        RETURN_NULL();    }    switch (Z_TYPE_P(uservar)) {        case IS_NULL:            php_printf("NULL/n");            break;        case IS_BOOL:            php_printf("Boolean: %s/n", Z_LVAL_P(uservar) ? "TRUE" : "FALSE");            break;        case IS_LONG:            php_printf("Long: %ld/n", Z_LVAL_P(uservar));            break;        case IS_DOUBLE:            php_printf("Double: %f/n", Z_DVAL_P(uservar));            break;        case IS_STRING:            php_printf("String: ");            PHPWRITE(Z_STRVAL_P(uservar), Z_STRLEN_P(uservar));            php_printf("/n");            break;        case IS_RESOURCE:            php_printf("Resource/n");            break;        case IS_ARRAY:            php_printf("Array/n");            break;        case IS_OBJECT:            php_printf("Object/n");            break;        default:            php_printf("Unknown/n");    }    RETURN_TRUE;}

編寫一個簡單的測試指令碼:

<?php     hello_dump(1234);    echo '<br/>';    hello_dump('terrylee');    echo '<br/>';    hello_dump(array('foo', 'bar'));?>

運行後效果如下:

在PHP擴充中對於使用者傳過來的參數,本質上都是一個zval結構,我們需要調用一些轉換函式進行強制類型轉換(zend_parse_parameters函數會對基本類型做轉換),Zend引擎提供了convert_to_xxx系列函數協助我們進行類型轉換:

convert_to_boolean_ex()

   
強制轉換為布爾類型。若原來是布爾值則保留,不做改動。長整型值0、雙精確度型值0.0、Null 字元串或字串‘0’還有空值 NULL 都將被轉換為
FALSE(本質上是一個整數 0)。數組和對象若為空白則轉換為 FALSE,否則轉為 TRUE。除此之外的所有值均轉換為
TRUE(本質上是一個整數 1)。

convert_to_long_ex()

   
強制轉換為長整型,這也是預設的整數類型。如果原來是空值NULL、布爾型、資源當然還有長整型,則其值保持不變(因為本質上都是整數
0)。雙精確度型則被簡單取整。包含有一個整數的字串將會被轉換為對應的整數,否則轉換為 0。空的數組和對象將被轉換為 0,否則將被轉換為 1。

convert_to_double_ex()

   
強制轉換為一個雙精確度型,這是預設的浮點數類型。如果原來是空值 NULL
、布爾值、資源和雙精確度型則其值保持不變(只變一下變數類型)。包含有一個數位字串將被轉換成相應的數字,否則被轉換為
0.0。空的數組和對象將被轉換為 0.0,否則將被轉換為 1.0。

convert_to_string_ex()

   
強制轉換為數組。若原來就是一數組則不作改動。對象將被轉換為一個以其屬性為鍵名,以其屬性值為索引值的數組。(方法強制轉換為字串。空值 NULL
將被轉換為空白字串。布爾值 TRUE 將被轉換為 ‘1’,FALSE
則被轉為一個Null 字元串。長整型和雙精確度型會被分別轉換為對應的字串,數組將會被轉換為字串‘Array’,而對象則被轉換為字串‘Object’。

convert_to_array_ex(value)

   

強制轉換為數組。若原來就是一數組則不作改動。對象將被轉換為一個以其屬性為鍵名,以其屬性值為索引值的數組。(方法將會被轉化為一個‘scalar’鍵,
索引值為方法名)空值 NULL 將被轉換為一個空數組。除此之外的所有值都將被轉換為僅有一個元素(下標為 0)的數組,並且該元素即為該值。

convert_to_object_ex(value)

    強制轉換為對象。若原來就是對象則不作改動。空值 NULL 將被轉換為一個Null 物件。數組將被轉換為一個以其鍵名為屬性,索引值為其屬性值的對象。其他類型則被轉換為一個具有‘scalar’屬性的對象,‘scalar’屬性的值即為該值本身。

convert_to_null_ex(value)

    強制轉換為空白值 NULL。

關於zval結構的介紹就到這裡了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.