日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

PHP扩展开发指南

發布時間:2025/5/22 php 128 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP扩展开发指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.1?????使用數組

曾講到,PHP數組本質上就是個HashTable,因此訪問數組就是對HashTable進行操作,Zend為我們提供的一組數組函數也只是對HashTable操作進行了簡單包裝而已。

來看創建數組,由于數組也是存在于zval里的,因此要先用MAKE_STD_ZVAL()宏創建一個zval,之后調用如下宏將其轉化為一個空數組:

array_init(zval*)

接下來是朝數組中添加元素,這對關聯數組元素和非關聯數組元素要采用不同操作。

?

1.1.1?關聯數組元素

關聯數組采用char*作為key,zval*作為value,可以使用如下宏將已有的zval加入數組或者更新已有元素:

int add_assoc_zval(zval *arr, char *key, zval *value)

需要特別注意的是,Zend不會復制zval,只會簡單的儲存其指針,并且不關心任何引用計數,因此不能將其他變量的zval或者是棧上的zval傳給它,只能用MAKE_STD_ZVAL()宏構建。

Zend為常用的類型定義了相應的API,以簡化我們的操作:

add_assoc_long(zval *array, char *key, long n);
add_assoc_bool(zval *array, char *key, int b);
add_assoc_resource(zval *array, char *key, int r);
add_assoc_double(zval *array, char *key, double d);
add_assoc_string(zval *array, char *key, char *str, int duplicate);
add_assoc_stringl(zval *array, char *key, char *str, uint length, int duplicate);
add_assoc_null(zval *array, char *key);

當函數發現目標元素已經存在時,會首先遞減其原zval的refcount,然后才插入新zval,這就保證了原zval引用信息的正確性。這種行為是通過HashTable.pDestructor(參見1.2.1)實現的,每次刪除一個元素時,HashTable都將對被刪元素調用這個函數指針,而數組為其HashTable設置的函數指針就是用來處理被刪除zval的引用信息。

另外,查看這些函數的源代碼可以發現一個有意思的現象,它們沒有直接使用HashTable操作,而是使用變量符號表操作,可見關聯數組和變量符號表就是一種東西。

Zend沒有提供刪除和獲取數組元素的函數,此類操作只能使用HashTable函數或者是2.6節的變量符號表操作。

1.1.2非關聯數組元素

非關聯數組沒有key,使用index作為hash,相應函數和上面關聯數組的十分類似:

add_index_zval(zval *array, uint idx, zval *value);
add_index_long(zval *array, uint idx, long n);
add_index_bool(zval *array, uint idx, int b);
add_index_resource(zval *array, uint idx, int r);
add_index_double(zval *array, uint idx, double d);
add_index_string(zval *array, uint idx, char *str, int duplicate);
add_index_stringl(zval *array, uint idx, char *str, uint length, int duplicate);
add_index_null(zval *array, uint idx);

如果只是想插入值,而不指定index的話,可以使用如下函數:

add_next_index_zval(zval *array, zval *value);
add_next_index_long(zval *array, long n);
add_next_index_bool(zval *array, int b);
add_next_index_resource(zval *array, int r);
add_next_index_double(zval *array, double d);
add_next_index_string(zval *array, char *str, int duplicate);
add_next_index_stringl(zval *array, char *str, uint length, int duplicate);
add_next_index_null(zval *array);

1.2??????使用資源

1.2.1? 注冊資源類型

1.1.1節曾經提到,所謂資源就是內部數據的handle(但是這句話并不全對),使用資源是比較簡單的,首先是注冊一個資源類型:

int zend_register_list_destructors_ex( rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number);

第一個參數是函數指針,當資源不再被使用或者模塊將被卸載時,Zend使用它來銷毀資源,稍候再作介紹;第二個參數和第一個類似,只是它被用來銷毀持久性資源(*);type_name是資源名稱,用戶可以使用var_dump函數來讀取;module_number是模塊號,在啟動函數中可以獲取該值。

注冊過程其實就是將我們傳入的參數放到一個內部數據結構,然后把這個數據結構放入一個沒有使用key的HashTable里,該函數返回的值,也就是所謂“資源類型id”,其實就是HashTable的index。

1.2.1? 注冊資源

注冊完資源類型后,就可以注冊一個該類型的資源了:

1ZEND_REGISTER_RESOURCE(
2rsrc_result,
3rsrc_pointer,
4rsrc_type)

src_pointer是個指針類型,就是你的資源的handle, 通常是指向內部數據的指針,當然也可以是index或者其它標志符;rsrc_type是上面獲取的資源類型id;rsrc_result是個已有的zval,注冊完成后,資源的id就被放入該zval,同時其type也被設為IS_RESOURCE,通常是傳入return_value,以將資源返回給用戶。

在內部,Zend使用如下數據結構表示一個資源:

1typedef struct _zend_rsrc_list_entry {
2????void *ptr;
3????int type;
4????int refcount;
5} zend_rsrc_list_entry;

ptr和type就是我們在上面傳入的參數;refcount是引用計數,由Zend維護,當引用減到0時,Zend會銷毀該資源。不出所料的是,這個數據結構也被組織在一個HashTable里,并且沒有使用key,僅僅使用index——這就是zval里存放的東西。現在資源的整個脈絡已經清晰:通過zval可以獲得資源id,通過資源id可以獲得資源handle和資源類型id,通過資源類型id可以獲得資源的銷毀函數。 現在講一下銷毀函數:

1typedef void (*rsrc_dtor_func_t)(
2zend_rsrc_list_entry *rsrc
3TSRMLS_DC);

rsrc是需要被銷毀的資源,我們在函數的實現中可以通過它獲得資源的handle,并且加以處理,比如釋放內存塊、關閉數據庫連接或是關閉文件描述符等。

1.2.3 ?獲取資源

當創建了資源后,用戶通常都要調用創建者提供的函數來操作資源,此時我們需要從用戶傳入的zval中取出資源:

1ZEND_FETCH_RESOURCE(
2rsrc,? rsrc_type,
3passed_id, default_id,
4resource_type_name, resource_type)

首個參數用于接收handle值,第二個參數是handle值的類型,這個函數會擴展成“rsrc = (rsrc_type) zend_fetch_resource(…)”,因此應該保證rsrc是rsrc_type類型的;passed_id是用戶傳入的zval,這里使用zval**類型,函數從中取得資源id;default_id用來直接指定資源id,如果該值不是-1,則使用它,并且忽略passed_id,所以通常應該使用-1;resource_type_name是資源名稱,當獲取資源失敗時,函數使用它來輸出錯誤信息;resource_type是資源類型,如果取得的資源不是該類型的,則函數返回NULL,這用于防止用戶傳入一個其他類型資源的zval。

不過,這個宏確實比較難用,用其底層的宏反倒更加容易些:

1zend_list_find(id, type)

id是要查找的資源id;type是int*類型,用于接收取出的資源的類型,可以用它來判斷這是不是我們想要的資源;函數最后返回資源的handle,失敗返回NULL。

1.2.4? 維護引用計數

通常,當用戶對資源類型的PHP變量執行賦值或是unset之類操作時,Zend會自動維護資源的引用計數。但有時,我們也需要手動進行,比如我們要復用一個數據庫連接或者用戶調用我們提供的close操作關閉一個文件,此時可以使用如下宏:

1zend_list_addref(id)
2zend_list_delete(id)

id是資源id,這兩個宏分別增加和減少目標資源的引用計數,第二個宏還會在引用計數減到0時,調用先前注冊的函數銷毀資源。

轉載于:https://www.cnblogs.com/lsl8966/archive/2012/12/10/2811944.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的PHP扩展开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 合欢视频在线观看 | 99re6在线精品视频免费播放 | 网站在线播放 | 日本久久久久久 | 男女操操操 | 和漂亮岳做爰3中文字幕 | 久草福利资源在线观看 | 国产综合在线播放 | 国产农村妇女毛片精品 | 中文字幕免费高清视频 | 视频一区二区在线观看 | 中文字幕人乱码中文字 | 天天色综网 | 在线观看中文字幕 | 瑟瑟视频在线观看 | 国产精品天美传媒 | 91学生片黄 | 日韩女优网站 | 天天干,天天操,天天射 | 哪里可以免费看毛片 | 少妇媚药按摩中文字幕 | 成人午夜淫片100集 伊人久久国产 | 亚洲国产精品久久久久久6q | www.在线视频 | 欧美九九视频 | 欧美老女人性视频 | 国产欧美日韩精品区一区二污污污 | 精品一区在线观看视频 | 国模无码视频一区二区三区 | 中文字幕免费在线观看 | 男女午夜视频在线观看 | 欧洲精品在线观看 | 国产黑丝精品 | 一区三区视频在线观看 | 精品人妻无码在线 | 黄色小视频免费网站 | 91视频成人免费 | 欧美亚洲日本国产 | 啦啦啦免费高清视频在线观看 | 成人午夜精品一区二区三区 | 欧美亚洲一区 | 婷婷伊人综合中文字幕 | a级国产视频 | 特级西西444www高清大胆 | 在线观看视频一区 | 欧美性bbw| 9l视频自拍蝌蚪9l视频成人 | 长河落日电视连续剧免费观看 | 天天影视亚洲 | 国产二级毛片 | 天堂av网手机版 | 99riAv国产精品无码鲁大师 | 亚洲色图偷| 亚洲视频天堂 | 日韩精品视频网 | 美女高潮网站 | jizz日本视频 | 国产日韩在线看 | √8天堂资源地址中文在线 欧美精品在线一区二区 | 亚洲高清中文字幕 | 黄色99视频 | 99热最新在线 | 最近中文字幕免费视频 | 精品日韩在线 | 日韩精品视频在线 | 高潮一区二区三区 | 亚洲欧美日韩精品永久在线 | 98国产精品 | 午夜精品久久99蜜桃的功能介绍 | 插插影视 | 亚洲精品国产美女 | 一区二区三区 中文字幕 | 国产嘿咻| 天天看夜夜看 | 中国黄色免费网站 | 欧美婷婷精品激情 | 亚洲黄在线| 亚洲男性天堂 | 美女精品网站 | 少妇无套内谢免费视频 | 国产精品免费看久久久无码 | 久久久88 | 亚洲欧美日韩精品在线观看 | 在线免费黄色 | 午夜影院| 久久久久国产一区二区三区潘金莲 | 天天干天天操天天摸 | 国产成人av一区二区三区 | 亚洲欧美变态另类丝袜第一区 | 日韩av综合在线 | 欧美国产精品一区二区 | 欧洲黄色录像 | 久久黄色小说 | 在线播放第一页 | 日韩最新av | 99er精品视频 | 26uuu成人网| 国产精品xxxxx | 色盈盈影院 |