PHP擴展開發教程5 - 擴展函數的參數類型(1)

PHP擴展是高級PHP程序員必須瞭解的技能之一,對於一個初入門的PHP擴展開發者,怎麼才能開發一個成熟的擴展,進入PHP開發的高級領域呢?本系列開發教程將手把手帶您從入門進入高級階段。
本教程系列在linux下面開發(推薦使用centos),php版本用的是5.6,並假設您有必定的linux操做經驗和c/c++基礎。
有問題須要溝通的朋友請加QQ技術交流羣32550793和我溝通。

前面兩節介紹瞭如何用PHP-CPP編寫經常使用的擴展函數,擴展類。對怎麼使用PHP-CPP開發擴展應該已經很熟悉了,下面晉級學習一下關於擴展函數參數類型方面的內容。php

下面教程內容的相關源碼已經上傳到github上面。linux

git clone https://github.com/elvisszhang/phpcpp_param.git

1、相關知識:PHP-CPP參數類型指定方式

有時候,咱們開發的函數,咱們但願只能傳入特定的類型,例如字符串運算的函數只能傳入字符串參數,數值運算的函數只能傳入數字參數,數組操做的函數只能傳入數組參數。c++

下面是擴展中如何指定一個函數參數類型的樣例代碼git

#include <phpcpp.h>

void example(Php::Parameters &params)
{
}

extern "C" {
    PHPCPP_EXPORT void *get_module() {
        static Php::Extension myExtension("my_extension", "1.0");
        myExtension.add<example>("example", {
            Php::ByVal("a", Php::Type::Numeric),
            Php::ByVal("b", "ExampleClass"),
            Php::ByVal("c", "OtherClass")
        });
        return myExtension;
    }
}

上面的 Php::ByVal 是表明值類型的參數的設定方式,聰明點的你應該猜到相對應還有一個 Php::ByRef的表明引用類型的參數設定方式。惋惜的是在php5.x擴展上面,通過實驗證實,引用方式的參數設定無效。程序員

2、相關知識:Php::ByVal函數說明

Php::ByVal 是表明值類型的參數的設定方式,總共有兩個函數原型定義。github

第一種原型是給標量,數組,對象,匿名函數等參數類型使用的,其C++的函數定義以下。數據庫

/**
 *  ByVal 值類型的參數的設定方式
 *  @param  name        參數名稱
 *  @param  type        參數類型
 *  @param  required    參數是否必填,默認必填
 */
ByVal(const char *name, Php::Type type, bool required = true);

第二種原型是給具備特定類名的函數參數使用的,其C++的函數定義以下。centos

/**
 *  ByVal 值類型的參數的設定方式
 *  @param  name        參數名稱
 *  @param  classname   參數類名
 *  @param  nullable    是否能夠爲空
 *  @param  required    參數是否必填,默認必填
 */
ByVal(const char *name, const char *classname, bool nullable = false, bool required = true);
值得注意的是,PHP不存在所謂函數參數名這個說法,上面函數參數裏面的name只是起一個助記符的做用,主要是在參數類型錯誤等異常狀況下,拋出異常的錯誤信息裏面使用,方便用戶知道具體是哪一個參數有問題。

3、相關知識:Php::Type參數類型說明

ByVal函數中的Php::Type是個C++的枚舉量,表明PHP-CPP的函數參數,總共支持如下11種類型。數組

Php::Type::Null     - 表示任何類型均可以傳入
Php::Type::Numeric  - 整數類型
Php::Type::Float    - 數值類型,支持整數、單精度浮點數、雙精度浮點數
Php::Type::Bool     - 布爾類型
Php::Type::Array    - 數組類型
Php::Type::Object         - 對象類型
Php::Type::String         - 字符串類型
Php::Type::Resource       - 資源類型(保存有爲打開文件、數據庫鏈接、圖形畫布區域等的特殊句柄)
Php::Type::Constant       - 常量類型
Php::Type::ConstantArray  - 常量數組類型
Php::Type::Callable       - 函數類型

除了 Php::Type::Array or Php::Type::Object 這兩個類型的參數使用起來比較特殊,必須使用專用的對應的C++類來操做。其餘類型使用起來基本上差異不大,由於PHP::Value這個類已經作了類型重載處理,。函數

4、代碼演示:階乘運算

對於階乘運算函數,咱們都知道,須要並且只需傳入一個正整數類型便可。
下面是該擴展函數的C++源碼

//演示階乘
Php::Value pm_factorial(Php::Parameters &params)
{
    int n = (int)params[0];
    if(n < 0 )
        return 0;
    int i,f=1;
    for(i=1;i<=n;i++)
        f *= i;
    return f;
}

註冊擴展函數的代碼

myExtension.add<pm_factorial>("pm_factorial", {
            Php::ByVal("a", Php::Type::Numeric)
});

PHP測試代碼(test/1.php)

<?php
echo PHP_EOL . '-----TEST pm_factorial()-----' . PHP_EOL;
var_dump( pm_factorial() );

echo PHP_EOL . '-----TEST pm_factorial(\'abc\')-----' . PHP_EOL;
var_dump( pm_factorial('abc','def') );

echo PHP_EOL . '-----TEST pm_factorial(\'5\')-----' . PHP_EOL;
var_dump( pm_factorial('5') );

echo PHP_EOL . '-----TEST pm_factorial(0)-----' . PHP_EOL;
var_dump( pm_factorial(0) );


echo PHP_EOL . '-----TEST pm_factorial(10)-----' . PHP_EOL;
var_dump( pm_factorial(10) );

echo PHP_EOL . '-----TEST pm_factorial(-10)-----' . PHP_EOL;
var_dump( pm_factorial(-10) );

echo PHP_EOL . '-----TEST pm_factorial(5.3)-----' . PHP_EOL;
var_dump( pm_factorial(5.3) );
?>

測試返回結果

# php test/1.php

-----TEST pm_factorial()-----
PHP Warning:  pm_factorial() expects at least 1 parameter(s), 0 given in /data/develop/phpcpp_param/test/1.php on line 3
NULL

-----TEST pm_factorial('abc')-----
int(1)

-----TEST pm_factorial('5')-----
int(120)

-----TEST pm_factorial(0)-----
int(1)

-----TEST pm_factorial(10)-----
int(3628800)

-----TEST pm_factorial(-10)-----
int(0)

-----TEST pm_factorial(5.3)-----
int(120)

根據以上測試結果,能夠總結出:

  1. 對於整數類型參數,會自動把浮點數強制轉成整形。
  2. 參數不足的時候,將會生成一個PHP警告,返回值爲NULL。
  3. 整數類型的參數自動會轉換字符串類型,沒法轉換時則轉換成0。

5、代碼演示:兩個數值(浮點數)類型參數相加

以演示兩個數字相加爲例,咱們但願傳入兩個參數,並且兩個參數都是數值類型。
下面是該擴展函數的C++源碼

//演示兩個數相加
Php::Value pm_add(Php::Parameters &params)
{
    return params[0] + params[1];
}

註冊擴展函數的代碼

myExtension.add<pm_add>("pm_add", {
            Php::ByVal("a", Php::Type::Float),
            Php::ByVal("b", Php::Type::Float)
});

PHP測試代碼(test/2.php)

<?php
echo PHP_EOL . '-----TEST pm_add()-----' . PHP_EOL;
var_dump( pm_add() );

echo PHP_EOL . '-----TEST pm_add(1)-----' . PHP_EOL;
var_dump( pm_add(1) );

echo PHP_EOL . '-----TEST pm_add(\'abc\',\'def\')-----' . PHP_EOL;
var_dump( pm_add('abc','def') );

echo PHP_EOL . '-----TEST pm_add(\'1\',\'2\')-----' . PHP_EOL;
var_dump( pm_add('1','2') );

echo PHP_EOL . '-----TEST pm_add(1,2)-----' . PHP_EOL;
var_dump( pm_add(1,2) );

echo PHP_EOL . '-----TEST pm_add(1.3,2.4)-----' . PHP_EOL;
var_dump( pm_add(1.3,2.4) );
?>

運行測試代碼,返回結果

# php test/2.php 

-----TEST pm_add()-----
PHP Warning:  pm_add() expects at least 2 parameter(s), 0 given in /data/develop/phpcpp_param/test/1.php on line 3
NULL

-----TEST pm_add(1)-----
PHP Warning:  pm_add() expects at least 2 parameter(s), 1 given in /data/develop/phpcpp_param/test/1.php on line 6
NULL

-----TEST pm_add('abc','def')-----
int(0)

-----TEST pm_add('1','2')-----
int(3)

-----TEST pm_add(1,2)-----
int(3)

-----TEST pm_add(1.3,2.4)-----
float(3.7)

根據以上測試結果,能夠總結出:

  1. 對於數值類型參數,整數,浮點數都支持。
  2. 參數不足的時候,將會生成一個PHP警告,返回值爲NULL。
  3. 數值類型的參數自動會轉換字符串類型的數值,沒法轉換時則轉換成0。

因爲篇幅有限,其餘的參數類型下一章節繼續演示。

6、參考文獻

PHP-CPP官網 - 關於函數參數

相關文章
相關標籤/搜索