搜尋
首頁後端開發php教程Linux 下PHP扩展开发系列:二. 一个典型的扩展开发

 

看完前言中所说的一些内容后,各位应该对PHP扩展开发有个笼统的了解了,可能有些人会觉得开发扩展很麻烦很复杂,实际上并非如此,这一篇我们就快速进入角色,开发出我们的第一个扩展。

 

一、编译PHP

开发之前还需要先准备好PHP源码并编译,过程如下:

tar -zxvf php-5.3.9.tar.gzcd php-5.3.9

我使用的是php5.3.9,解压后,我们进入了PHP源码目录,然后我们直接编译并增加php.ini:

./configure --prefix=/usr/local/webserver/php --enable-fastcgi --enable-fpm --enable-debugmake && make installcp /home/soft/php-5.3.9/php.ini-development /usr/local/webserver/php/lib/php.ini

编译完成,我没有静态编译其他扩展,但是开启了debug,这个后面会用到。然后修改php.ini中对应的项,这里就不细说了。

现在把PHP相关加入环境变量中,省去后面很多工作:

vim /root/.bash_profile

我是使用root,其他不同用户修改对应用户目录下的.bask_profile文件,在文件中的PATH后面加入:/usr/local/webserver/php/bin/,类似下面这样:

PATH=$PATH:$HOME/bin:/usr/local/webserver/php/bin/

环境变量设置好了,我们查看下PHP版本:

 OK,编译工作完成,让我们继续。

 

二、典型开发流程

一个典型的扩展开发流程如下图:

 

 三、扩展功能定义

先定义我们要完成的扩展功能:

    该扩展只有一个功能,就是重写PHP的系统函数ip2long(),解决ip2long在32位与64位系统下值不同的问题(该问题是因为32位与64位的整形范围不同导致的,具体原因请google)。

    我们新的ip2long固定返回32位有符号整数,范围-2147483648 到 2147483647,与32位系统相同。

    我们的扩展名称为 myip,函数名为 ip2long32

    扩展的功能与名称都OK了,现在按流程进行开发。

 

四、正式开发  

    1. 生成开发骨架

    首先进入源码扩展目录:

 

cd /home/soft/php-5.3.9/ext

 

    然后了解下PHP提供的扩展骨架工具ext_skel生成骨架,ext_skel的用法如下:

./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]           [--skel=dir] [--full-xml] [--no-help]  --extname=module   module is the name of your extension(模块名,会在当前目录创建一个该名称子目录)  --proto=file       file contains prototypes of functions to create(函数原型定义文件)  --stubs=file       generate only function stubs in file  --xml              generate xml documentation to be added to phpdoc-cvs  --skel=dir         path to the skeleton directory(设置骨架生成的目录,不设置该项则默认在ext/extname下)  --full-xml         generate xml documentation for a self-contained extension                     (not yet implemented)  --no-help          don't try to be nice and create comments in the code                     and helper functions to test if the module compiled (生成的代码中不显示各种帮助注释)

    这次我们准备用到两个选项,--extname=myip 即定义扩展的名称,而--proto=myip.pro则是定义扩展的函数原型,首先我们生成扩展函数原型文件:

vim myip.pro

    加入以下内容:

int ip2long32(string ip)

    这意味着我们的扩展中有一个函数,返回值为int型,输入为string。

    这时候执行以下命令生成扩展骨架:

./ext_skel --extname=myip --proto=myip.pro

    OK,这时候你会发现在当前PHP扩展目录下生成了一个子目录myip,进入myip看下:

cd myipll

    你会发现生成了一堆文件,如下图:

    此时我们就可以进行第二步了。

    2. 修改config.m4

    关于config.m4文件的功能,我们留到后面的文章中在详细进行说明,现在只说明要做什么。

    使用vim编辑config.m4:

vim config.m4

    将16至18行行首的dnl去掉,如下:

    具体这样做的原因在后面的文章中会说明,这边我们直接退出并保存config.m4,继续进入下一步。

    3. 编码

    重头戏来啦,终于可以进入myip.c中进行功能的编码了,一起欢呼下吧!

vim myip.c

   找到下图所示的位置:

   图中就是扩展骨架工具根据我们提供的函数原型生成的对应函数,此处有几个需要注意的地方:

   1. PHP_FUNCTION:是PHP核心定义的一个宏,与ZEND_FUNCTION相同,用于定义扩展函数,实际生成的函数名称为zif_ip2long32。

   2. zend_parse_parameters:由于PHP为弱类型语言,而C是强类型,因此需要使用该函数用于接收PHP传入的参数,并进行一定的类型转换,将PHP的变量转为C语言能够辨认的类型。

      zend_parse_parameters函数的原型如下:

zend_parse_parameters(int num_args TSRMLS_CC, char *type_spec, …);

      参数说明:

      num_args:传递给函数的参数个数。通常的做法是使用宏 ZEND_NUM_ARGS()。       TSRMLS_CC:线程安全,总是传递TSRMLS_CC宏。 详解:http://www.54chen.com/php-tech/what-is-tsrmls_cc.html       type_spec:第三个参数是一个字符串,指定了函数期望的参数类型       ...:需要随参数值更新的变量列表]

type_spec是格式化字符串,其常见的含义如下:

参数   代表着的类型

b   Boolean

l   Integer 整型

d   Floating point 浮点型

s   String 字符串

r   Resource 资源

a   Array 数组

o   Object instance 对象

O   Object instance of a specified type 特定类型的对象

z   Non-specific zval 任意类型~

Z   zval**类型

f   表示函数、方法名称

   我们将该函数修改为如下内容:

 PHP_FUNCTION(ip2long32) {         char *ip = NULL;         int argc = ZEND_NUM_ARGS();         int ip_len;          if (zend_parse_parameters(argc TSRMLS_CC, "s", &ip, &ip_len) == FAILURE) {                 return;         }                  int32_t ip_int32;         unsigned char ip1, ip2, ip3, ip4;                  sscanf(ip, "%hhu.%hhu.%hhu.%hhu", &ip1, &ip2, &ip3, &ip4);         ip_int32 = (int32_t)((ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4);         RETURN_LONG(ip_int32); }

    功能完成了,这边有个RETURN_LONG(ip_int32)比较特殊,这也是PHP内核提供的宏,用于返回值给PHP,具体说明如下:

设置返回值并且结束函数        设置返回值             宏返回类型和参数
RETURN_LONG(l)           RETVAL_LONG(l)           整数
RETURN_BOOL(b)          RETVAL_BOOL(b)           布尔数(1或0)
RETURN_NULL()           RETVAL_NULL()           NULL
RETURN_DOUBLE(d)        RETVAL_DOUBLE(d)        浮点数
RETURN_STRING(s, dup)       RETVAL_STRING(s, dup)       字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s
RETURN_STRINGL(s, l, dup)     RETVAL_STRINGL(s, l, dup)    长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。
RETURN_TRUE           RETVAL_TRUE            返回布尔值true。注意到这个宏没有括号。
RETURN_FALSE           RETVAL_FALSE           返回布尔值false。注意到这个宏没有括号。
RETURN_RESOURCE(r)        RETVAL_RESOURCE(r)       资源句柄。

    编码完成了,保存并退出,然后我们可以开始编译了。

    4. 编译

phpize./configure --with-php-config=/usr/local/webserver/php/bin/php-configmake && make install

    不出意外的话编译完成后会有如下提示:

Installing shared extensions:     /usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/

    进入该目录看下是否已经有myip.so,有的话最后我们就可以修改php.ini载入该so文件

    5. 修改php.ini

cd /usr/local/webserver/php/libvim php.ini

    修改extension_dir,并加入 extension = myip.so

extension_dir = "/usr/local/webserver/php/lib/php/extensions/debug-non-zts-20090626/"extension = myip.so

    退出保存,并重启php,如果是使用Phpfpm的话可以执行如下命令:

kill -USR2 `cat /usr/local/webserver/php/var/run/php-fpm.pid`

    看下扩展是否正常载入:

[root@tm977 lib]# php -m|grep myipmyip

    说明已经正常载入了,最后我们测试下扩展函数吧!

    6. 测试

php -r "var_dump(ip2long32('192.168.1.1'));"int(-1062731519)php -r "var_dump(ip2long('192.168.1.1'));"  int(3232235777)

    如上所示,ip2long32输出的是32位有符号整数,而ip2long输出的是64位无符号整数,大功告成!

 

五、小结

    通过这一次的开发示例,是不是觉得其实开发一个扩展很简单?

    确实是的,但是也别高兴的太早了,实际上要开发出功能强大的扩展远不是这么简单的事情,后面的文章我会继续深入,一边开发一边了解更加复杂的PHP核心代码。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP如何處理對象克隆(克隆關鍵字)和__clone魔法方法?PHP如何處理對象克隆(克隆關鍵字)和__clone魔法方法?Apr 17, 2025 am 12:24 AM

PHP中使用clone關鍵字創建對象副本,並通過\_\_clone魔法方法定制克隆行為。 1.使用clone關鍵字進行淺拷貝,克隆對象的屬性但不克隆對象屬性內的對象。 2.通過\_\_clone方法可以深拷貝嵌套對象,避免淺拷貝問題。 3.注意避免克隆中的循環引用和性能問題,優化克隆操作以提高效率。

PHP與Python:用例和應用程序PHP與Python:用例和應用程序Apr 17, 2025 am 12:23 AM

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。

描述不同的HTTP緩存標頭(例如,Cache-Control,ETAG,最後修飾)。描述不同的HTTP緩存標頭(例如,Cache-Control,ETAG,最後修飾)。Apr 17, 2025 am 12:22 AM

HTTP緩存頭的關鍵玩家包括Cache-Control、ETag和Last-Modified。 1.Cache-Control用於控制緩存策略,示例:Cache-Control:max-age=3600,public。 2.ETag通過唯一標識符驗證資源變化,示例:ETag:"686897696a7c876b7e"。 3.Last-Modified指示資源最後修改時間,示例:Last-Modified:Wed,21Oct201507:28:00GMT。

說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1?說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1?Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP:服務器端腳本語言的簡介PHP:服務器端腳本語言的簡介Apr 16, 2025 am 12:18 AM

PHP是一種服務器端腳本語言,用於動態網頁開發和服務器端應用程序。 1.PHP是一種解釋型語言,無需編譯,適合快速開發。 2.PHP代碼嵌入HTML中,易於網頁開發。 3.PHP處理服務器端邏輯,生成HTML輸出,支持用戶交互和數據處理。 4.PHP可與數據庫交互,處理表單提交,執行服務器端任務。

PHP和網絡:探索其長期影響PHP和網絡:探索其長期影響Apr 16, 2025 am 12:17 AM

PHP在過去幾十年中塑造了網絡,並將繼續在Web開發中扮演重要角色。 1)PHP起源於1994年,因其易用性和與MySQL的無縫集成成為開發者首選。 2)其核心功能包括生成動態內容和與數據庫的集成,使得網站能夠實時更新和個性化展示。 3)PHP的廣泛應用和生態系統推動了其長期影響,但也面臨版本更新和安全性挑戰。 4)近年來的性能改進,如PHP7的發布,使其能與現代語言競爭。 5)未來,PHP需應對容器化、微服務等新挑戰,但其靈活性和活躍社區使其具備適應能力。

為什麼要使用PHP?解釋的優點和好處為什麼要使用PHP?解釋的優點和好處Apr 16, 2025 am 12:16 AM

PHP的核心優勢包括易於學習、強大的web開發支持、豐富的庫和框架、高性能和可擴展性、跨平台兼容性以及成本效益高。 1)易於學習和使用,適合初學者;2)與web服務器集成好,支持多種數據庫;3)擁有如Laravel等強大框架;4)通過優化可實現高性能;5)支持多種操作系統;6)開源,降低開發成本。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境