PHP擴展是高級PHP程序員必須瞭解的技能之一,對於一個初入門的PHP擴展開發者,怎麼才能開發一個成熟的擴展,進入PHP開發的高級領域呢?本系列開發教程將手把手帶您從入門進入高級階段。
本教程系列在linux下面開發(推薦使用centos),php版本用的是5.6,並假設您有必定的linux操做經驗和c/c++基礎。
有問題須要溝通的朋友請加QQ技術交流羣32550793和我溝通。
上一章演示了一個hello world擴展,你們基本瞭解了用PHP-CPP開發的擴展的C++源碼的基本樣式。下面一塊兒開發一個簡單的數學運算庫(mymath)來熟悉如何導出各類接口函數。
mymath數學庫的代碼已放在github上,能夠直接git下載或者瀏覽器打開網頁下載源碼。php
git下載命令行html
git clone https://github.com/elvisszhang/phpcpp_mymath.git
瀏覽器下載網址和倉庫網址同樣:https://github.com/elvisszhan...linux
函數功能:打印100之內的素數c++
函數名稱:mm_print_pn_100git
如何註冊擴展函數
必須在get_module函數體中,註冊函數 mm_print_pn_100,以便能在php中能直接調用。程序員
PHPCPP_EXPORT void *get_module() { // 必須是static類型,由於擴展對象須要在PHP進程內常駐內存 static Php::Extension extension("mymath", "1.0.0"); //這裏能夠添加你要暴露給PHP調用的函數 extension.add<mm_print_pn_100>("mm_print_pn_100"); // 返回擴展對象指針 return extension; }
函數聲明及代碼以下。
函數不須要參數,函數的參數列表裏面什麼也不用放,空着就行。函數不須要返回值,返回值類型設置爲void。github
//打印100之內的素數 void mm_print_pn_100() { int x = 2; int y = 1; int line = 0; while (x <= 100){ int z = x - y; //z隨y遞減1 int a = x%z; //取餘數 if (a == 0) { //若是x被z整除 if (z == 1) {//若是z爲1(x是質數) Php::out << x << " ";//輸出x line ++;//每行輸出的數的數量加1 } x ++; //x加1 y = 1;//y還原 } else {//若是沒有被整除 y ++;//y加1,下一次循環中z減1 } if (line == 10) {//每輸出10個數 Php::out << std::endl;//輸出一個換行 line = 0;//還原line } } if (line != 0) //最後一行輸出換行 Php::out << std::endl; Php::out.flush(); }
PHP測試代碼centos
<?php //打印100之內的素數 mm_print_pn_100();
運行以上PHP代碼,輸出結果是數組
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
函數功能:計算一、二、三、...、100的和
函數名稱:mm_sum_1_100瀏覽器
註冊函數 mm_sum_1_100,註冊方式同上一節
extension.add<mm_sum_1_100>("mm_sum_1_100");
函數聲明及代碼以下。
函數不須要參數,函數參數列表設置爲空就能夠。
函數有返回值,返回值類型設置爲 Php::Value。因爲Php::value 重載了構造函數和operator = 運算符,常見數據類型(整形,字符串,浮點數,數組等)能夠直接返回。
//獲取1-100的和 Php::Value mm_sum_1_100() { int sum = 0; int i; for(i=1;i<=100;i++){ sum += i; } return sum; //能夠直接返回sum值,自動生成 Php::value 類型 }
PHP測試代碼:
<?php $sum = mm_sum_1_100(); echo 'sum (1~100) = ' . $sum . PHP_EOL; ?>
運行以上PHP代碼,輸出結果是
sum (1~100) = 5050
函數功能:計算任意給定整數,打印該整數之內的全部素數
函數名稱:mm_print_pn_any
註冊函數 mm_print_pn_any,註冊方式同上一節
extension.add<mm_print_pn_any>("mm_print_pn_any");
函數聲明及代碼以下。因爲須要參數,函數參數須要寫成Php::Parameters ¶ms,因爲沒有返回值,返回值類型設置void。
另外須要檢測參數是否輸入,參數的類型也須要檢測是否是整形。不檢測直接用的話,代碼容易出異常。
//任意給定一個整數,打印出小於等於該整數的全部素數 void mm_print_pn_any(Php::Parameters ¶ms) { //檢查必須輸入一個參數 if(params.size() == 0){ Php::out << "error: need a parameter " << std::endl; return; } //檢查參數必須是整形 if( params[0].type() != Php::Type::Numeric){ Php::out << "error: parameter must be numeric" << std::endl; return; } //檢查數字必須大於1 int number = params[0]; if(number <= 1){ Php::out << "error: parameter must be larger than 1" << std::endl; return; } //檢查參數必須大於0 int x = 2; int y = 1; int line = 0; while (x <= number){ int z = x - y; //z隨y遞減1 int a = x%z; //取餘數 if (a == 0) { //若是x被z整除 if (z == 1) {//若是z爲1(x是質數) Php::out << x << " ";//輸出x line ++;//每行輸出的數的數量加1 } x ++; //x加1 y = 1;//y還原 } else {//若是沒有被整除 y ++;//y加1,下一次循環中z減1 } if (line == 10) {//每輸出10個數 Php::out << std::endl;//輸出一個換行 line = 0;//還原line } } if (line != 0) //最後一行輸出換行 Php::out << std::endl; Php::out.flush(); }
PHP測試代碼
<?php echo '---runing mm_print_pn_any()---' . PHP_EOL; mm_print_pn_any(); echo PHP_EOL . '---runing mm_print_pn_any(\'xyz\')---' . PHP_EOL; mm_print_pn_any('xyz'); echo PHP_EOL . '---runing mm_print_pn_any(200)---' . PHP_EOL; mm_print_pn_any(200); ?>
運行以上PHP代碼,輸出結果是
---runing mm_print_pn_any()--- error: need a parameter ---runing mm_print_pn_any('xyz')--- error: parameter must be numeric ---runing mm_print_pn_any(200)--- 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
函數功能:給定一系列參數,計算其總和
函數名稱:mm_sum_all
註冊擴展函數 mm_sum_all,註冊方式同上一節
extension.add<mm_sum_all>("mm_sum_all");
函數聲明及代碼以下。
//獲取全部參數的和 Php::Value mm_sum_all(Php::Parameters ¶ms) { int sum = 0; for (auto ¶m : params){ //字符串類型能夠自動轉換成整形 sum += param; } return sum; }
PHP測試代碼
<?php $sum = mm_sum_all(1,2,'3','5'); //字符串類型能夠自動轉換成整形 echo 'sum (1,2,\'3\',\'5\') = ' . $sum . PHP_EOL; ?>
測試輸出結果:
sum (1,2,'3','5') = 11
函數功能:給定一個數組類型的參數,計算數組所有元素的總和
函數名稱:mm_sum_array
註冊函數 mm_sum_array ,註冊方式同第一節
函數聲明及代碼以下。
//獲取全部數組各元素的和 Php::Value mm_sum_array(Php::Parameters ¶ms) { //沒有給定參數,返回0 if(params.size() == 0){ return 0; } //參數類型不是數組,轉成整形返回 if( params[0].type() != Php::Type::Array){ return (int)params[0]; } //數組中的元素逐個相加 int sum = 0; Php::Value array = params[0]; int size = array.size(); int i; for(i=0;i<size;i++){ sum += array.get(i); } return sum; }
PHP測試代碼
<?php $nums = array(1,3,5,7); $sum = mm_sum_array($nums); echo 'sum (array(1,3,5,7)) = ' . $sum . PHP_EOL; ?>
測試輸出結果:
sum (array(1,3,5,7)) = 16
上面函數的返回值都是標量類型,數組是PHP特別經常使用的類型,若是想返回一個數組類型,可使用c++的std::vector,PHP-CPP會貼心的把它自動轉換成PHP認識的數組類型。
咱們如今的演示函數功能是「返回30之內的全部素數的數組」。擴展裏面註冊函數的方式同第一節。
函數聲明及代碼以下。
//獲取30之內的全部素數 Php::Value mm_get_pn_30() { std::vector<int> pn; int x = 2; int y = 1; while (x <= 30){ int z = x - y; //z隨y遞減1 int a = x%z; //取餘數 if (a == 0) { //若是x被z整除 if (z == 1) {//若是z爲1(x是質數) pn.push_back(x); //放數組中去 } x ++; //x加1 y = 1;//y還原 } else {//若是沒有被整除 y ++;//y加1,下一次循環中z減1 } } return pn; }
PHP測試代碼
<?php $pn = mm_get_pn_30(); var_dump($pn); ?>
測試輸出結果:
array(10) { [0]=> int(2) [1]=> int(3) [2]=> int(5) [3]=> int(7) [4]=> int(11) [5]=> int(13) [6]=> int(17) [7]=> int(19) [8]=> int(23) [9]=> int(29) }