PHP擴展開發教程3 - 開發一個咱們本身的數學函數庫

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

1、不帶參數,沒有返回值的擴展函數寫法

函數功能:打印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

2、不帶參數,有返回值的擴展函數寫法

函數功能:計算一、二、三、...、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

3、帶有參數,沒有返回值的擴展函數寫法

函數功能:計算任意給定整數,打印該整數之內的全部素數

函數名稱:mm_print_pn_any

註冊函數 mm_print_pn_any,註冊方式同上一節

extension.add<mm_print_pn_any>("mm_print_pn_any");

函數聲明及代碼以下。因爲須要參數,函數參數須要寫成Php::Parameters &params,因爲沒有返回值,返回值類型設置void。
另外須要檢測參數是否輸入,參數的類型也須要檢測是否是整形。不檢測直接用的話,代碼容易出異常。

//任意給定一個整數,打印出小於等於該整數的全部素數
void mm_print_pn_any(Php::Parameters &params)
{
    //檢查必須輸入一個參數
    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

4、標量型參數,有返回值的擴展函數寫法

函數功能:給定一系列參數,計算其總和

函數名稱:mm_sum_all

註冊擴展函數 mm_sum_all,註冊方式同上一節

extension.add<mm_sum_all>("mm_sum_all");

函數聲明及代碼以下。

//獲取全部參數的和
Php::Value mm_sum_all(Php::Parameters &params)
{
    int sum = 0;
    for (auto &param : 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

5、數組型參數,有返回值的擴展函數寫法

函數功能:給定一個數組類型的參數,計算數組所有元素的總和

函數名稱:mm_sum_array

註冊函數 mm_sum_array ,註冊方式同第一節

函數聲明及代碼以下。

//獲取全部數組各元素的和
Php::Value mm_sum_array(Php::Parameters &params)
{
    //沒有給定參數,返回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

6、返回值類型是數組的擴展函數寫法

上面函數的返回值都是標量類型,數組是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)
}

7、參考文獻

c++質數斷定及輸出質數表
PHP-CPP函數開發幫助

相關文章
相關標籤/搜索