首頁 > 後端開發 > php教程 > 使用C和PHP-CPP開發PHP擴展:高級

使用C和PHP-CPP開發PHP擴展:高級

Joseph Gordon-Levitt
發布: 2025-02-18 12:30:12
原創
723 人瀏覽過

使用C 和PHP-CPP開發PHP擴展:高級主題和最佳實踐

關鍵要點

  • 使用C 和PHP-CPP開發PHP擴展涉及高級主題,例如返回“this”指針、返回複雜對象指針、公開__toString魔術方法、鏈接成員函數調用以及PHP中的異常拋出和處理。
  • 對於需要在未來用於非PHP項目的軟件、數據結構或算法的項目,或者需要使用尚未作為PHP擴展提供的工具或庫的項目,PHP-CPP庫是理想的選擇。它還提供C/C 代碼的性能優勢,同時保持結構化、面向對象的代碼,便於理解和維護。
  • PHP-CPP庫可用於個人和商業項目。但是,雖然庫本身是免費的,但可能需要時間和資源來學習如何有效地使用它並維護PHP擴展。
  • 使用C 進行PHP擴展開發的常見挑戰包括正確管理內存、處理錯誤和異常以及PHP和C 之間的接口。可以通過深入了解PHP和C 、使用良好的編程實踐以及利用PHP-CPP提供的功能和工具來克服這些挑戰。

在我之前的文章中,我介紹了使用C (第一篇文章和第二篇文章)創建PHP擴展的PHP-CPP庫。在後一篇文章中,我演示了使用Complex類進行複數運算的編寫PHP擴展的面向對象方面。

Developing PHP Extensions with C   and PHP-CPP: Advanced

該介紹並不完整,因為該文章的主要重點更多地放在演示PHP-CPP的面向對象能力上,而不是面向對象的實現細節上。

在本文中,我們將進一步深入研究Complex庫的開發,添加更多成員函數,並解決使用PHP-CPP編寫具有面向對像功能的PHP擴展中的一些高級主題:

  • 返回this指針;
  • 返回Complex對象指針,即Complex *;
  • 公開__toString魔術方法;
  • 鍊式成員函數調用;
  • 拋出異常並在PHP中處理它

完整的Complex庫源代碼以及測試PHP腳本位於此Github存儲庫中。

讓我們開始吧。

準備工作

在第一篇文章中解釋了準備環境的整個過程。

在C 中返回this指針

如第二篇文章所述,我們使用成員函數對複數執行各種數學運算。在此演示中,我們將實現四個這樣的函數:add、sub、mul和div。我將首先解釋前三個。 div函數涉及異常處理,稍後將討論。

讓我們看一下mul函數(用於乘法)。 add和sub函數大致相同。

Php::Value add(Php::Parameters &params) {
    Php::Value t = params[0];
    Complex *a = (Complex *) t.implementation();

    r += (double) a->getReal();
    i += (double) a->getImage();

    return this;
}
登入後複製
登入後複製
登入後複製

注意:在本文中,我將不介紹一些之前討論過的基本主題,例如修改Makefile和ini文件、註冊成員函數、類和命名空間等。請參考前面的部分了解這些內容。

將this指針從C 返回到PHP很簡單。在這個C 函數內部,this指針(作為Complex *類型)可以作為Php::Value類型返回到PHP。轉換不會丟失任何對象信息。它也不需要顯式類型轉換。

返回Complex對象指針

返回this通常意味著對象本身已更改。但在某些情況下,我們可能希望返回一個新對象並保持“當前”對象(調用對象)不變。

在我們的Complex類中,我們有一個這樣的函數,它返回給定複數的共軛數(a bi變為a-bi)。

Php::Value add(Php::Parameters &params) {
    Php::Value t = params[0];
    Complex *a = (Complex *) t.implementation();

    r += (double) a->getReal();
    i += (double) a->getImage();

    return this;
}
登入後複製
登入後複製
登入後複製

這裡的關鍵點是,我們必須使用Php::Object將我們的Complex *對象顯式轉換為Php::Object,因此當該對象稍後由PHP腳本解析時,可以正確保留類信息並保持其可訪問性。

此函數的第一個參數是類類型,在本例中為trComplex。我使用此名稱是因為我已將此類(“Complex”)包裝到單獨的命名空間(“tr”)中。

第二個參數是要傳回的對象。

返回新的類實例比只返回this指針要棘手一些,但只要您閱讀了文檔並找到了正確的部分,仍然是可以管理的。有關更多用法示例,您可能需要閱讀PHP-CPP官方文檔中的這一部分。

公開__toString魔術方法

在我們的類中,有一個__toString函數,它以更易讀的方式打印複數,例如:1 2i。在我之前的文章中,此函數未公開(或在PHP-CPP術語中“註冊”),但仍然可以從PHP內部調用。但是,為了使此函數在我們應用一些數學運算(例如“echo $a->add($b)->sub($c)”)後能夠在Complex對像上調用,我們需要在已編譯的擴展中顯式註冊它:

Php::Value conjugate() {
    Complex *t = new Complex();

    t->r = r;
    t->i = -i;

    return Php::Object("tr\Complex", t);
}
登入後複製
登入後複製

我們在PHP-CPP存儲庫中提交的問題Issue #150詳細討論了我們必須這樣做的原因。

鍊式成員函數調用

必須在此類中實現的一件事是能夠鏈接成員函數,以便我們可以進行如下計算:$a->add($b)->sub($c)。結果仍然應該能夠調用其成員函數。

這是通過上述方法完成的,即返回this指針到PHP。但是,較舊的PHP-CPP庫在取消引用對象時存在錯誤,如果鏈接方法調用,則會創建“段錯誤”。

已提交問題(#151),並提交了包含PHP-CPP源代碼補丁的提交。如果您使用的是舊版本的PHP-CPP庫來編譯PHP-CPP庫和您自己的庫,請更新PHP源代碼並重新編譯和重新安裝PHP-CPP庫和您的庫。

如提交摘要所解釋:

complex.method("__toString", &Complex::__toString);
登入後複製
登入後複製

我很高興我自己的項目工作可以幫助我使用的庫變得更好。

異常拋出和PHP中的處理

我們的Complex類中還有兩個函數可能會將異常拋回PHP進行處理:div和phi。前者執行除法運算,後者返回複數的角度,如其替代表示形式極坐標表示法(r,θ)所示。

如果將復數作為參數(或調用者)傳遞,但其實部和虛部為0,則這兩個操作都可能失敗。對於這兩個操作,我們需要進行異常處理。請記住,我們要在C 代碼中拋出異常,而PHP腳本將捕獲異常並進行必要的處理:

Php::Value add(Php::Parameters &params) {
    Php::Value t = params[0];
    Complex *a = (Complex *) t.implementation();

    r += (double) a->getReal();
    i += (double) a->getImage();

    return this;
}
登入後複製
登入後複製
登入後複製

在PHP腳本中,我們像這樣捕獲此異常:

Php::Value conjugate() {
    Complex *t = new Complex();

    t->r = r;
    t->i = -i;

    return Php::Object("tr\Complex", t);
}
登入後複製
登入後複製

上面的代碼段將顯示如下文本行:

complex.method("__toString", &Complex::__toString);
登入後複製
登入後複製

很簡單,對吧?在我們的擴展中構造的C 異常被傳回PHP並被正確捕獲。此外,我們可以像處理其他PHP代碼拋出的原生PHP異常一樣操作異常!

測試所有函數

最後,我們可以通過make && sudo make install為我們的PHP安裝編譯和安裝complex.so擴展。如果一切順利,我們可以通過在終端中發出以下命令來驗證擴展的安裝:

<code>修复问题#151,链式方法调用无法正常工作……
……因为每个对象的引用计数未正确更新,这导致即使对象已分配给不同的变量,该对象也会被销毁。</code>
登入後複製

終端應該顯示一行顯示“/etc/php5/cli/conf.d/complex.ini”,我們可以確定我們的擴展已安裝並準備由任何PHP腳本調用。

注意:如果我們檢查此擴展的Makefile,我們將看到我們正在將此PHP擴展安裝到其CLI環境中。如果我們想安裝此擴展以便Apache加載它,我們更改以下行:

Php::Value div(Php::Parameters &params) {
    Php::Value t = params[0];
    Complex *b = (Complex*) t.implementation();

    double t1 = b->mod() * b->mod();

    if (t1 == 0)
        throw Php::Exception("Division by zero");

    double tr = r * (double) (b->getReal()) + i * (double) (b->getImage());
    double ti = i * (double) (b->getReal()) - r * (double) (b->getImage());

    r = tr / t1;
    i = ti / t1;

    return this;
}
登入後複製

此擴展的測試PHP腳本如下所示,並帶有一些註釋:

$a=new tr\Complex(1,2);
$c=new tr\Complex(); //$c实际上是0+0i

try
{
    $res=$a->div($c);
}
catch(Exception $e)
{
    echo "Caught exception: ".$e->getMessage()."\n";
}
}
登入後複製

所有測試腳本都應該正確運行,並且異常被正確捕獲。

結論

這總結了我關於使用C 構建PHP擴展的這個強大庫的3篇文章系列。我們介紹了基礎知識、面向對象方面以及面向對象編程中的一些高級主題。我們還幫助PHP-CPP有所改進。

我們還能用PHP-CPP做什麼?我將引用幾行我從Emiel Bruijntjes(PHP-CPP的合著者)收到的電子郵件通信:

如果您正在從事一個項目,並且具有以下一個或多個要求,則PHP-CPP庫是理想的選擇: – 您正在處理軟件/數據結構/算法,並且您希望確保將來您的軟件也可以用於非PHP項目。 – 您想使用尚未作為PHP擴展提供的工具或庫。 – 您希望獲得C/C 代碼的更好性能(與PHP相比),但您還想構建結構化、面向對象的代碼,以便其他開發人員/同事易於理解和維護。

可能性是巨大的:框架(如Phalcon)、模板語言(如Smarty或Twig)等等。

請留下您的評論和觀點,讓我們知道您使用此庫做了什麼!

使用C 開發PHP擴展的常見問題解答

使用C 開發PHP擴展的好處是什麼?

使用C 開發PHP擴展具有多種好處。首先,它允許您在PHP應用程序中利用C 的強大功能和靈活性。這可以提高性能,尤其是在計算密集型任務中。其次,它提供了一種在PHP環境中重用現有C 代碼的方法,這可以節省大量的開發時間和精力。最後,它使您能夠創建自定義PHP擴展,這些擴展可以擴展PHP的功能並提供標準PHP庫中不可用的功能。

如何開始使用C 進行PHP擴展開發?

要開始使用C 進行PHP擴展開發,您需要對PHP和C 編程語言都有基本的了解。您還需要安裝PHP開發環境和C 編譯器。安裝這些先決條件後,您可以開始用C 編寫PHP擴展。網上有很多資源可用,包括教程和示例代碼,可以指導您完成此過程。

什麼是PHP-CPP,它如何幫助PHP擴展開發?

PHP-CPP是一個用於使用C 開發PHP擴展的庫。它提供了一組C 類和方法,簡化了編寫PHP擴展的過程。使用PHP-CPP,您可以以更自然和直觀的方式編寫PHP擴展,使用C 熟悉的語法和概念。這可以使開發過程更高效,並且減少錯誤。

我可以將PHP-CPP用於商業項目嗎?

是的,PHP-CPP是開源軟件,可用於個人和商業項目。但是,重要的是要理解,雖然庫本身是免費的,但您可能需要投入時間和資源來學習如何有效地使用它以及維護您的PHP擴展。

使用C 進行PHP擴展開發的一些常見挑戰是什麼,我該如何克服它們?

使用C 進行PHP擴展開發的一些常見挑戰包括正確管理內存、處理錯誤和異常以及PHP和C 之間的接口。可以通過深入了解PHP和C 、使用良好的編程實踐以及利用PHP-CPP提供的功能和工具來克服這些挑戰。

如何調試用C 編寫的PHP擴展?

可以使用標準C 調試工具調試用C 編寫的PHP擴展。此外,PHP-CPP提供了一些可以幫助調試的功能,例如異常處理和錯誤報告。

我可以將PHP-CPP與其他C 庫一起使用嗎?

是的,PHP-CPP可以與其他C 庫一起使用。這使您可以利用PHP擴展中的各種C 功能。

如何提高用C 編寫的PHP擴展的性能?

您可以通過使用高效的算法和數據結構、最大限度地減少內存使用以及優化C 代碼來提高PHP擴展的性能。此外,PHP-CPP提供了一些可以幫助提高性能的功能,例如直接訪問PHP變量和函數。

我可以為PHP-CPP項目貢獻代碼嗎?

是的,PHP-CPP項目是開源的,歡迎社區的貢獻。您可以通過報告錯誤、建議新功能或提交補丁來貢獻代碼。

在哪裡可以找到更多關於使用C 進行PHP擴展開發的資源?

網上有很多資源可用於學習使用C 進行PHP擴展開發。這些資源包括教程、示例代碼、文檔和論壇。此外,PHP-CPP網站提供了大量關於使用該庫的信息和資源。

以上是使用C和PHP-CPP開發PHP擴展:高級的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板