站長資訊網
        最全最豐富的資訊網站

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        php入門到就業線上直播課:進入學習
        Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

        眾所周知,作為一名phper,對php有限的功能感到尷尬,比如:調用ffmpeg視頻處理工具。沒有專門的擴展來操作的,什么?利用php system函數調用?對于開源的php腳本,這太不安全了!

        這個時候作為深資的phper會考慮開發php擴展,在擴展中實現對ffmpeg的操作。

        目前c站上對于rust如何開發php擴展的文章幾乎沒有,就連開發php擴展流程的文章也都很對付。特此撰寫此文!!!

        為什么要使用php擴展?

        優點:

        1、php擴展是C開發的,那速度沒得說。

        2、耦合性高,它的出現就是用來增強php的。

        3、安全性高,畢竟擴展是編譯后的程序,代碼不開源。

        缺點:

        1、需針對php版本及系統環境進行開發,那么就比較麻煩了。也就是說7.4版本的php,liunx環境下開發的擴展,只支持該php版本及系統。

        2、需要會C、C++,當然本文是以rust進行開發,對C的數據類型進行了解,對rust FFI的操作及數據類型轉換需精通。

        3、調試相對麻煩。

        為什么要用rust開發php擴展?

        原因很簡單,這還要說起rust的語言特性。

        1、因“所有權”的特性使你的程序更安全,不會像C那樣出現各種“玄學BUG”。

        2、擁有C一樣的性能。

        3、畢竟是最受歡迎的語言,我很看好它的發展。

        rust開發php擴展流程:

        當然,rust目前是沒有專門開發php擴展的骨架。所以我的邏輯也很簡單,利用rust開發靜態庫暴露給C【涉及FFI的了解】。我們在php官方骨架中直接引入rust靜態庫調用其方法即可。

        開發環境

        寶塔【CentOS 7.6】、GCC【涉及php擴展骨架的編譯,我這里系統內置就有,如果編譯擴展報相關錯了自行安裝】、對應php版本源碼、web環境【寶塔中安裝對應php版本、nginx、mysql等等】

        開發整體流程:

        1、準備寶塔

        寶塔安裝流程:CentOS寶塔搭建(超詳細)_一碼超人的博客-CSDN博客_centos 寶塔

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        這里我們以開發php7.4擴展為例。

        2、下載php7.4 liunx版源碼

        php官網:PHP: Hypertext Preprocessor

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        注意!該源碼版本必須與你環境php版本完全一致!!!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        下載完畢:

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        3、上傳php源碼到寶塔

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        /usr/phper
        登錄后復制

        在usr下創建一個phper文件夾,然后將源碼壓縮包上傳到此處。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        解壓該壓縮包

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        4、創建一個我們自己的擴展

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        /usr/phper/php-7.4.30/ext目錄下有這么一個php文件,它可以創建擴展!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        注意設置命令行版本,因為接下來利用php命令必須是版本一致的!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        在剛剛的目錄下,點擊終端,輸入創建擴展命令。

        php ext_skel.php --ext 擴展名稱
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        這里就多出了一個新的擴展源碼文件。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        在該目錄下點擊終端,輸入:

        phpize
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        接著輸入:

        ./configure --with-php-config=/www/server/php/74/bin/php-config
        登錄后復制

        注意這個參數php路徑,如果是別的版本,請自行在寶塔里安裝找到對應版本路徑,它們都是放一起的。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        回車開始進行檢查了

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        最后輸入:

        make
        登錄后復制

        進行編譯。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        這個目錄下便是編譯出來的so擴展最終文件了!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        讓我們看下默認生成的擴展有哪些功能

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        查看主文件【需了解php擴展骨架,這里以它默認給的為例】

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        也就是說,剛剛編譯出來的擴展,是有這兩個函數的,咱們測試一下玩玩。

        注意!每次修改主文件,都需要重新按上述命令跑一遍,否則不生效,很奇怪!

        phpize ./configure --with-php-config=/www/server/php/74/bin/php-config make
        登錄后復制

        登錄后復制

        5、使用擴展

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        復制剛剛生成的擴展文件到我們php環境的擴展里

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        配置php.ini加載hello.so擴展

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        extension = hello.so
        登錄后復制

        保存后記得重新啟動下php,否則不生效的!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        在文件管理中點擊終端,輸入:

        php -m
        登錄后復制

        可以看到我們的擴展在列表中了。

        創建一個站點,測試下擴展中兩個函數。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        看好,php版本是7.4

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        訪問站點

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        沒有問題哦!

        當然也可以通過命令行運行php腳本查看結果【前提是網站那里php命令行版本設置的7.4】

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        php index.php
        登錄后復制

        OK!從創建到生成到使用擴展的流程結束,接下來才進入正題,開始用rust開發擴展。

        6、rust與php擴展的整合開發

        開發工具:CLion

        需要rust環境與CLion中rust插件的安裝與配置,這個自行去百度,比我想象中的全!

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        創建一個hello命名的庫項目

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        我們寫兩個導出函數,分別是加法功能和base64字符串解析功能。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        lib.rs

        #![crate_type = "staticlib"]  extern crate libc;  //使用C類型約束 use std::ffi::{CStr, CString}; use libc::{c_char, c_int};  //add_int【參數:兩個c語言的int類型】:對兩個int類型數值進行相加 #[no_mangle] pub extern "C" fn add_int(x:c_int, y:c_int) -> c_int{     //兩個數相加     return x + y; }  //base64_decode函數【參數:c語言的*char類型】:對字符串進行base64解碼 #[no_mangle] pub extern "C" fn base64_decode(s:*const c_char) -> *mut c_char {     //c char類型轉&str     let h = unsafe{CStr::from_ptr(s).to_str().unwrap()};     //base64 解碼     let s = base64::decode(h.to_string());     if let Err(_s) = s {         panic!("類型錯誤!");     }     let n = String::from_utf8(s.unwrap().clone()).unwrap();     //String 轉 C CString     let a = CString::new(n.as_str()).unwrap();     //C CString 轉 C char     //這里實屬無奈,因為rust ffi中闡述,對字符串返回只能是該字符串地址,所以需要該方法進行返回C才能接收到!     let r = a.into_raw();     return r; }
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        Cargo.toml

        [package] name = "hello" version = "0.1.0" edition = "2021"  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "hello" crate-type = ["staticlib"]  [dependencies] libc = "*" base64 = "0.12.1"
        登錄后復制

        注意在編譯過程中涉及系統類型,不然在引入該靜態庫編譯擴展可能報錯,提示不支持。

        編譯64位靜態庫

        rustup target add x86_64-unknown-linux-musl cargo build --target x86_64-unknown-linux-musl --release
        登錄后復制

        編譯32位靜態庫

        rustup target add i686-unknown-linux-musl cargo build --target i686-unknown-linux-musl --release
        登錄后復制

        這里我們是64位系統。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        會生成一個.a文件,該文件便是liunx支持的靜態庫文件。

        生成支持C語言的膠水頭文件【用于C調用該庫需要寫的函數聲明,很方便】

        創建cbindgen.toml文件

        內容:

        language = "C"
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        安裝cbindgen,創建頭文件。

        cargo install --force cbindgen cbindgen --config cbindgen.toml --crate 項目名稱 --output 頭文件名稱.h
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        自動生成了C語言的函數聲明hello.h文件,用于調用。

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        回到之前我們創建的hello擴展

        創建lib文件夾

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        將剛剛編譯出來的靜態庫.a文件上傳到lib目錄下

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        將剛剛創建的.h頭文件上傳到擴展目錄下

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        配置.m4預編譯文件【關鍵】

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        設置引入lib文件夾中的靜態庫文件一文詳解Rust怎么開發PHP擴展(Liunx版)

          PHP_ADD_LIBRARY_WITH_PATH(hello, /usr/phper/php-7.4.30/ext/hello/lib, HELLO_SHARED_LIBADD)   PHP_SUBST(HELLO_SHARED_LIBADD)
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        保存.m4

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        編寫主文件

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        /* hello extension for PHP */  #ifdef HAVE_CONFIG_H # include "config.h" #endif  #include "php.h" #include "ext/standard/info.h" #include "php_hello.h" #include "hello.h"//引入頭文件 /* For compatibility with older PHP versions */ #ifndef ZEND_PARSE_PARAMETERS_NONE #define ZEND_PARSE_PARAMETERS_NONE()  	ZEND_PARSE_PARAMETERS_START(0, 0)  	ZEND_PARSE_PARAMETERS_END() #endif  /* {{{ void hello_test1()  */ PHP_FUNCTION(hello_test1) { 	ZEND_PARSE_PARAMETERS_NONE();      int num = add_int(1,2);//rust中兩個數相加函數并返回。      	php_printf("The extension %d is loaded and working!rn", num); } /* }}} */  /* {{{ string hello_test2( [ string $var ] )  */ PHP_FUNCTION(hello_test2) { 	char *var = "World"; 	size_t var_len = sizeof("World") - 1; 	zend_string *retval;  	ZEND_PARSE_PARAMETERS_START(0, 1) 		Z_PARAM_OPTIONAL 		Z_PARAM_STRING(var, var_len) 	ZEND_PARSE_PARAMETERS_END();      char *newstr = base64_decode(var);//rust中解析base64字符串并返回。      	retval = strpprintf(0, "Hello %s", newstr);  	RETURN_STR(retval); } /* }}}*/  /* {{{ PHP_RINIT_FUNCTION  */ PHP_RINIT_FUNCTION(hello) { #if defined(ZTS) && defined(COMPILE_DL_HELLO) 	ZEND_TSRMLS_CACHE_UPDATE(); #endif  	return SUCCESS; } /* }}} */  /* {{{ PHP_MINFO_FUNCTION  */ PHP_MINFO_FUNCTION(hello) { 	php_info_print_table_start(); 	php_info_print_table_header(2, "hello support", "enabled"); 	php_info_print_table_end(); } /* }}} */  /* {{{ arginfo  */ ZEND_BEGIN_ARG_INFO(arginfo_hello_test1, 0) ZEND_END_ARG_INFO()  ZEND_BEGIN_ARG_INFO(arginfo_hello_test2, 0) 	ZEND_ARG_INFO(0, str) ZEND_END_ARG_INFO() /* }}} */  /* {{{ hello_functions[]  */ static const zend_function_entry hello_functions[] = { 	PHP_FE(hello_test1,		arginfo_hello_test1) 	PHP_FE(hello_test2,		arginfo_hello_test2) 	PHP_FE_END }; /* }}} */  /* {{{ hello_module_entry  */ zend_module_entry hello_module_entry = { 	STANDARD_MODULE_HEADER, 	"hello",					/* Extension name */ 	hello_functions,			/* zend_function_entry */ 	NULL,							/* PHP_MINIT - Module initialization */ 	NULL,							/* PHP_MSHUTDOWN - Module shutdown */ 	PHP_RINIT(hello),			/* PHP_RINIT - Request initialization */ 	NULL,							/* PHP_RSHUTDOWN - Request shutdown */ 	PHP_MINFO(hello),			/* PHP_MINFO - Module info */ 	PHP_HELLO_VERSION,		/* Version */ 	STANDARD_MODULE_PROPERTIES }; /* }}} */  #ifdef COMPILE_DL_HELLO # ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() # endif ZEND_GET_MODULE(hello) #endif
        登錄后復制

        刪除之前生成的擴展文件

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        重新生成擴展一文詳解Rust怎么開發PHP擴展(Liunx版)

        phpize ./configure --with-php-config=/www/server/php/74/bin/php-config make
        登錄后復制

        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        大小都變了,說明我們的靜態庫在里面了哈哈。

        按上述使用擴展流程替換擴展

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        注意!替換擴展文件后要重啟PHP哦,不然不生效!

        7、測試rust開發的php擴展

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        網頁測試

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        命令行測試

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        也可以通過php擴展骨架直接進行測試

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        編寫要執行測試的擴展函數

        --TEST-- hello_test2() Basic test --SKIPIF-- <?php if (!extension_loaded('hello')) { 	echo 'skip'; } ?> --FILE-- <?php hello_test1(); var_dump(hello_test2('5LiA56CB6LaF5Lq6')); ?> --EXPECT-- string(11) "Hello World" string(9) "Hello PHP"
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        擴展目錄下直接輸入:

        make test
        登錄后復制

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        執行后 tests目錄下輸出了一個.out文件

        一文詳解Rust怎么開發PHP擴展(Liunx版)

        是不是這樣更方便了呢?

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 久久精品国产亚洲AV香蕉| www.亚洲精品| 99免费精品视频| 拍国产真实乱人偷精品| 88国产精品无码一区二区三区| 国产久热精品无码激情| 亚洲人成精品久久久久| 久久www免费人成精品香蕉| 9久热这里只有精品| 国产精品久久久久9999高清| 麻豆成人久久精品二区三区免费 | 欧美精品v欧洲精品| 亚洲精品无码久久久久AV麻豆| 精品国产亚洲一区二区在线观看 | 精品无码无人网站免费视频| 一本久久a久久精品vr综合| 久久夜色撩人精品国产| 精品91自产拍在线观看二区| 国产精品自在欧美一区| 国产精品亚洲一区二区在线观看| 在线观看91精品国产网站| 国产韩国精品一区二区三区久久| 亚洲午夜精品久久久久久app| 久久国产综合精品五月天| 精品久久久久久无码免费| 国产精品网址在线观看你懂的| 国产精品理论片在线观看| 国产精品 91 第一页| 国产在线精品观看免费观看| 精品久久久久久无码人妻热| 久久精品亚洲精品国产欧美| 日韩经典精品无码一区| 亚洲国产主播精品极品网红| 亚洲国产精品成人网址天堂| 久久人搡人人玩人妻精品首页| 精品欧美一区二区在线观看| 日本精品一区二区三区在线视频| 亚洲精品视频在线观看你懂的| 综合国产精品第一页| 日韩精品人妻系列无码专区免费| 国产精品网站在线观看免费传媒|