摘要:這里看到,表明你的擴(kuò)展已經(jīng)加載成功了,現(xiàn)在就可以調(diào)用這個擴(kuò)展函數(shù)了。是不是很簡單更多上面的例子還比較簡單,只是編寫了一個擴(kuò)展函數(shù)。
PHP-X是我在2017年年初創(chuàng)建的一個新項(xiàng)目。這個項(xiàng)目的目標(biāo)就是讓有一定工作經(jīng)驗(yàn)的PHP程序都能夠具備擴(kuò)展開發(fā)的能力。
0x00 初衷從2012年開始編寫swoole,現(xiàn)在算來已經(jīng)有5個年頭了。我發(fā)現(xiàn)編寫一個 PHP 擴(kuò)展這個工作非常艱難。PHP 程序員群體中,甚至可以說 100 人中都很難找出一個會編寫 PHP 擴(kuò)展的人來。PHP 官方對擴(kuò)展開發(fā)者非常不友好,源代碼中提供的Zend API極其難用,API復(fù)雜而且凌亂,充斥著各種宏的寫法。Zend API坑非常多,普通開發(fā)者很容易踩到坑里。出現(xiàn)各種莫名其妙的core dump問題。Zend API幾乎沒有任何文檔,開發(fā)者如果要真正掌握這項(xiàng)技能需要付出大量的學(xué)習(xí)時間。
于是我今年就冒出一個新的想法,基于我編寫swoole擴(kuò)展超過5年的經(jīng)驗(yàn),我試圖在Zend API和C++之間建立一個包裝層,讓PHP擴(kuò)展開發(fā)變得簡單。有一定C++基礎(chǔ)的PHPer都可以輕松得開發(fā)一個PHP擴(kuò)展。
PHP-X這個項(xiàng)目就這樣誕生了,開發(fā)只用了一個月的時間。它的開發(fā)效率非常高,在我公司中一個只工作了3年的 PHP 程序員,都可以做出一個擴(kuò)展來。接下來陸續(xù)在公司的幾個項(xiàng)目中進(jìn)行了快速驗(yàn)證。在3個的時間里修復(fù)了大量崩潰和內(nèi)存泄漏問題。目前穩(wěn)定性、性能、健壯性均已達(dá)到工業(yè)級水準(zhǔn)。
0x01 起步PHP-X本身基于C++11開發(fā),使用cmake進(jìn)行編譯配置。首先,你需要確定所有依賴項(xiàng)已安裝好。包括:
gcc-4.8 或更高版本
php-7.0 或更高版本,需要php7-dev包
cmake-2.8 或更高版本
然后安裝PHP-X。
git clone https://github.com/swoole/PHP-X.git cd PHP-X cmake . make -j 4 sudo make install
未出現(xiàn)任何編譯錯誤,會成功編譯出libphpx.so,并安裝到系統(tǒng)的lib目錄。頭文件會復(fù)制到系統(tǒng)的include目錄。這時需要執(zhí)行 sudo ldconfig刷新so文件緩存。
0x02 新建工程使用任意開發(fā)工具,新建一個test.cc源文件。首先需要引入phpx.h頭文件。然后使用using引入phpx的命名空間。PHP官方未使用C++,因此phpx直接使用了php作為命名空間。
#includeusing namespace std; using namespace php;
創(chuàng)建擴(kuò)展使用PHPX_EXTENSION宏來實(shí)現(xiàn)。在這宏中只需要new Extension即可創(chuàng)建擴(kuò)展。構(gòu)造方法接受2個參數(shù),第一個是擴(kuò)展的名稱,第二個是擴(kuò)展的版本號。在PHPX_EXTENSION宏中return這個擴(kuò)展對象的指針。
PHPX_EXTENSION() { Extension *ext = new Extension("test", "0.0.1"); return ext; }
0x03 增加函數(shù)這里必須使用 new Extension,而不能直接在棧上創(chuàng)建對象
一個PHP擴(kuò)展的主要作用就是提供擴(kuò)展函數(shù),擴(kuò)展函數(shù)由于是用C/C++代碼實(shí)現(xiàn),因此它的性能會比PHP用戶函數(shù)性能高幾十甚至上百倍。在phpx中實(shí)現(xiàn)函數(shù)非常簡單。使用PHPX_FUNCTION來實(shí)現(xiàn)擴(kuò)展函數(shù),然后調(diào)用Extension::registerFunction來注冊擴(kuò)展函數(shù)。
PHPX_FN是一個助手宏,實(shí)際上展開就是"cpp_hello_world", cpp_hello_world
PHPX_FUNCTION展開后,包含了2個變量,第一個是參數(shù)args,第二個是返回值retval
通過操作args和retval兩個變量,就可以實(shí)現(xiàn)函數(shù)的輸入和輸出
這里我們的代碼非常簡單,cpp_test($str, $n),調(diào)用這個函數(shù)返回一個$n個$str的數(shù)組。
#include0x04 編譯擴(kuò)展using namespace std; using namespace php; //聲明函數(shù) PHPX_FUNCTION(cpp_test); PHPX_EXTENSION() { Extension *ext = new Extension("test", "0.0.1"); ext->registerFunction(PHPX_FN(cpp_test)); return ext; } //實(shí)現(xiàn)函數(shù) PHPX_FUNCTION(cpp_test) { //args[1] 就是這個擴(kuò)展函數(shù)的第 2 個參數(shù) long n = args[1].toInt(); //將返回值 retval 初始化為數(shù)組 Array _array(retval); for(int i = 0; i < n; i++) { //args[0] 就是這個擴(kuò)展函數(shù)的第 1 個參數(shù) //append 方法表示向數(shù)組中追加元素 _array.append(args[0]); } }
編寫一個Makefile文件。內(nèi)容如下:
PHP_INCLUDE = `php-config --includes` PHP_LIBS = `php-config --libs` PHP_LDFLAGS = `php-config --ldflags` PHP_INCLUDE_DIR = `php-config --include-dir` PHP_EXTENSION_DIR = `php-config --extension-dir` test.so: test.cc c++ -DHAVE_CONFIG_H -g -o test.so -O0 -fPIC -shared test.cc -std=c++11 ${PHP_INCLUDE} -I${PHP_INCLUDE_DIR} -lphpx install: test.so cp test.so ${PHP_EXTENSION_DIR}/ clean: rm *.so
php-config 這個工具是PHP提供的,使用php-config可以得到PHP的安裝路徑、頭文件目錄、擴(kuò)展目錄、其他額外的編譯參數(shù)等等。
這個Makefile支持了3個指令,make編譯,make clean清理,make install安裝到擴(kuò)展目錄中。
這里可能需要root權(quán)限,使用sudo make install進(jìn)行安裝
直接從網(wǎng)頁復(fù)制,可能會出現(xiàn)tab制表符被替換為空格,請手工編輯一下Makefile使用tab縮進(jìn)
MacOS下需要在c++編譯參數(shù)中增加-undefined dynamic_lookup
編寫好之后執(zhí)行make install,就會編譯擴(kuò)展并將擴(kuò)展test.so安裝到PHP的擴(kuò)展目錄中。這時需要修改php.ini加入extension=test.so加載擴(kuò)展。
使用php -m來觀察你的擴(kuò)展是否正常加載。
php -m [PHP Modules] Core ctype curl date dom fileinfo filter gd hash iconv inotify json libxml mbstring mcrypt memcached mongodb mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql pdo_sqlite Phar posix redis Reflection session SimpleXML sockets SPL sqlite3 standard swoole test tokenizer xml xmlreader xmlwriter yac zlib zmq [Zend Modules]
這里看到test,表明你的擴(kuò)展已經(jīng)加載成功了,現(xiàn)在就可以調(diào)用cpp_test這個擴(kuò)展函數(shù)了。
0x05 執(zhí)行編寫一個test.php,內(nèi)容為:
執(zhí)行test.php:
php test.php array(3) { [0]=> string(5) "hello" [1]=> string(5) "hello" [2]=> string(5) "hello" }可以看到執(zhí)行結(jié)果符合預(yù)期。那么恭喜你,現(xiàn)在你已經(jīng)成功地開發(fā)了一個PHP擴(kuò)展了。是不是很簡單?
0x06 更多上面的例子還比較簡單,只是編寫了一個擴(kuò)展函數(shù)。要真正在實(shí)際項(xiàng)目中使用PHP-X你還有很多工作要做。
需要C++的功底
了解更多PHP-X的 API
另外配合使用Eclipse等IDE工具,可以實(shí)現(xiàn)API自動提示和補(bǔ)齊,開發(fā)起來會更順手。
相比Zend API,PHP-X要簡單易用地多了,相信你不會花太多時間就可以掌握此項(xiàng)技能。在接下來我會撰寫更多教程,教大家如何使用PHP-X實(shí)現(xiàn)擴(kuò)展類、資源、回調(diào)函數(shù)等更復(fù)雜的功能。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/25808.html
摘要:四使用語言開發(fā)是我重點(diǎn)推薦的擴(kuò)展開發(fā)框架,簡明易懂,功能強(qiáng)大,開發(fā)效率高,代碼易維護(hù),執(zhí)行速度快。優(yōu)點(diǎn)三支持,的擴(kuò)展開發(fā)有兩套擴(kuò)展開發(fā)框架,分別支持,,雖然框架代碼有兩個,但是接口卻是一樣的。 PHP擴(kuò)展是高級PHP程序員必須了解的技能之一,對于一個初入門的PHP擴(kuò)展開發(fā)者,怎么才能開發(fā)一個成熟的擴(kuò)展,進(jìn)入PHP開發(fā)的高級領(lǐng)域呢?本系列開發(fā)教程將手把手帶您從入門進(jìn)入高級階段。本教程系列...
摘要:接著上一篇文章,本文開始在擴(kuò)展內(nèi)實(shí)現(xiàn)類的定義和對象操作。因此定義類,需要在的回調(diào)中進(jìn)行。使用類名方法名即可。連接成功連接失敗在中不僅可以創(chuàng)建擴(kuò)展內(nèi)置的類,還可以創(chuàng)建代碼定義的類。 接著上一篇文章,本文開始在擴(kuò)展內(nèi)實(shí)現(xiàn)類的定義和對象操作。基于PHP-X提供的封裝,使用C++語言可以輕松地實(shí)現(xiàn)一個PHP的類,還可以在C++代碼中創(chuàng)建任意PHP對象,調(diào)用對象方法、讀寫對象的屬性。 0x00 ...
摘要:本文主要介紹內(nèi)置函數(shù)的使用,在擴(kuò)展開發(fā)中,會經(jīng)常用到這些內(nèi)置函數(shù),的封裝,使得調(diào)用這些函數(shù)像代碼一樣簡單。的使用方法與語言的是完全一致的。包括的超全局變量和其他代碼使用關(guān)鍵詞聲明的全局變量。 本文主要介紹PHP-X內(nèi)置函數(shù)的使用,在PHP擴(kuò)展開發(fā)中,會經(jīng)常用到這些內(nèi)置函數(shù),PHP-X的封裝,使得調(diào)用這些函數(shù)像PHP代碼一樣簡單。 echo 在擴(kuò)展中需要輸出一些內(nèi)容,可以使用echo函數(shù)...
摘要:總得來說,從大三開始到入職奇虎這年,一直處于自己探索階段,各種折騰,浪費(fèi)了不少青春,收獲總得來說不是很大。入職奇虎之后,有了一份穩(wěn)定的工作,從此一天當(dāng)作兩天來用,惡補(bǔ)我之前浪費(fèi)的青春。 經(jīng)過緊張的開發(fā),我終于費(fèi)了九牛二虎之力將 zendAPI 的項(xiàng)目官網(wǎng)做好上線了,眨眼已經(jīng)入職奇虎一年了,我也走完了我的職業(yè)生涯規(guī)劃的第一年,別問我之前4年干啥去了,我去瀟灑了 (拉著幾個大學(xué)同學(xué)創(chuàng)業(yè)去了...
摘要:項(xiàng)目是什么是對的接口使用的最新標(biāo)準(zhǔn)進(jìn)行而面向?qū)ο蟮姆庋b,從而屏蔽了底層的接口復(fù)雜性,加快開發(fā)擴(kuò)展的效率。國內(nèi)同類型的項(xiàng)目推薦目前國內(nèi)有一個跟比較類似的項(xiàng)目,這個項(xiàng)目是項(xiàng)目作者開發(fā),值得推薦。項(xiàng)目名字項(xiàng)目的地址是大家有興趣可以研究。 項(xiàng)目Logo showImg(https://segmentfault.com/img/bVVtW8?w=716&h=218); zendAPI 是什么? ...
閱讀 2334·2021-11-15 11:38
閱讀 3544·2021-09-22 15:16
閱讀 1186·2021-09-10 11:11
閱讀 3155·2021-09-10 10:51
閱讀 2919·2019-08-30 15:56
閱讀 2773·2019-08-30 15:44
閱讀 3184·2019-08-28 18:28
閱讀 3524·2019-08-26 13:36