首頁 > 後端開發 > php教程 > 通過PHP-CPP開始PHP擴展開發

通過PHP-CPP開始PHP擴展開發

Lisa Kudrow
發布: 2025-02-21 09:06:11
原創
410 人瀏覽過

通過PHP-CPP開始PHP擴展開發

在與PHP的交往中,您可能會考慮自己寫PHP擴展。我能想到的有幾個原因激發了我這樣做:

>

    >擴展PHP功能以進行一些非常特殊的用法(數學,統計,幾何等)。
  • 與純PHP實施相比,
  • 具有更高的性能和效率
  • 利用以前掌握的語言(對我,C)獲得的編程獲得的迅速性。
  • >
在選擇構建PHP擴展的工具方面,我們看到了兩種不同的方法:

    使用更多的PRHP語義,例如Zephir。
  • >使用更多的Pro-C/C語義,例如PHP-CPP,將在本文中解決。
  • 對我來說,選擇第二種方法的主要驅動器很簡單:我開始使用C/C進行編程愛好,因此我仍然更願意在C/C中編寫那些較低級別的模塊。 PHP-CPP的官方網站給出了其他一些理由。
>

鑰匙要點

PHP-CPP是一個用於開發PHP擴展的庫,允許C開發人員編寫PHP擴展,而無需直接與Zend API合作的複雜性。它寫在C 11中,並提供了有據可查和用戶友好的課程的集合。

> PHP-CPP正在迅速發展,建議使用Git克隆存儲庫以進行最新更新。它支持單線讀取的PHP安裝,並需要升級到G編譯器到4.8.x版或更高版本以兼容。
    >
  • > PHP-CPP提供了一個骨架擴展項目,其中包括一個main.cpp文件,用於編譯擴展名的製造文件以及用於擴展加載的.INI文件。可以定制骨架項目以適合個人需求,並使用“ make && sudo make install”命令進行編譯和安裝。
  • PHP-CPP支持四種類型的函數簽名,可以從PHP調用,並允許參數以數組形式通過值傳遞。它還允許功能導出/註冊,功能參數類型的規範以及以對象為導向的擴展的創建。
  • >安裝和配置
  • PHP-CPP正在迅速發展。在本文撰寫本文時,它以0.9.1版本(大約2天發布)。根據其文檔:“這是一個為即將推出的V1.0版本做準備的功能凍結版本”,因此我們有信心很快就會看到其1.0主要版本。 因此,至少在此期間,建議使用git克隆存儲庫,並通過git拉動獲得最新更新。
  • 注意:安裝上的PHP-CPP文檔指出,暫時,它“僅支持單線讀取PHP安裝”,因為“內部Zend Engine使用了非常奇怪的系統來確保線程安全性”。未來的發行版可能支持多線Readed PHP安裝,但讓我們暫時記住這一點,並遵守其當前限制。幸運的是,大多數PHP安裝都應該是“單線讀取的PHP安裝”。

    >

    > php-cpp寫在C 11中。因此,我的Ubuntu 12.04 LTS中安裝的G較舊版本不支持它。我們需要將G編譯器升級到上述4.8.x版本。有一篇文章詳細介紹了進行升級的步驟。請按照列出的說明進行操作。

    >另外,PHP-CPP彙編將使用php.h標頭文件。除非安裝PHP-DEV,否則通常在Ubuntu框中缺少此文件。我們可以通過發出此命令來安裝與PHP5相關的開發文件:

<span>sudo apt-get install php5-dev</span>
登入後複製
登入後複製
登入後複製

>升級G並安裝必要的標頭文件後,我們可以發布以下命令以編譯和安裝PHP-CPP庫文件(libphpcpp.so):>

<span>make && sudo make install</span>
登入後複製
登入後複製
登入後複製
登入後複製
彙編將很快。安裝後,libphpcpp.so文件將被複製到/usr/lib,所有PHP-CPP標頭文件將被複製到/usr/include/include and/usr/include/include/phpcpp文件夾。

>。 PHP-CPP LIB的安裝現已完成。這非常簡單,我們現在可以繼續進行編程部分。

在這樣做之前,我們將討論PHP-CPP中使用的一些重要概念和術語。完整的文檔可以在其官方網站上找到,並鼓勵每個人在執行任何真正的編程之前閱讀它。

骨架(空)擴展項目文件

PHP-CPP提供了一個骨架擴展項目,其中包含以下3個文件:

> main.cpp:包含get_module函數的主CPP文件(稍後將詳細討論)

>

makefile:示例製作文件以編譯擴展名

    yourextension.ini:僅包含一行擴展名加載
  • > makefile
  • >如果您熟悉 *NIX開發,那麼您熟悉此Makefile。應進行一些輕微的更改以自定義此文件以滿足我們的需求:

更改名稱=您對更有意義的extension,例如名稱=骨架。

>更改ini_dir = /etc/php5/conf.d匹配系統的配置。就我而言,它是ini_dir = /etc/php5/cli/conf.d。我修改了INI路徑,以首先啟用PHP CLI環境的擴展。

  • 這些都是我所做的所有更改。其餘的makefile可以保持原樣。
  • > yourextension.ini
>我將此文件重命名為skeleton.ini,然後更改了這樣的文件中的唯一行:

>

<span>sudo apt-get install php5-dev</span>
登入後複製
登入後複製
登入後複製

> main.cpp

在PHP-CPP提供的空項目中,此文件僅包含一個函數:get_module(),該函數下面摘錄:

<span>make && sudo make install</span>
登入後複製
登入後複製
登入後複製
登入後複製

>目前,讓我們更改此行以匹配我們打算創建的擴展名:>

當後者試圖加載所需的庫時,PHP調用了<span>extension=skeleton.so</span>來調用。 到目前為止,我們已經對空的項目進行了一些更改,以適應我們的需求。現在,我們可以編譯和安裝此項目並安裝擴展名:

接下來,我們需要將所需的文件複製到適當的文件夾中:>

<span><span>#include <phpcpp.h></span>
</span>
<span>/**
</span><span> *  tell the compiler that the get_module is a pure C function
</span><span> */
</span><span>extern "C" {
</span>
    <span>/**
</span><span>     *  Function that is called by PHP right after the PHP process
</span><span>     *  has started, and that returns an address of an internal PHP
</span><span>     *  strucure with all the details and features of your extension
</span><span>     *
</span><span>     *  @return void*   a pointer to an address that is understood by PHP
</span><span>     */
</span>    PHPCPP_EXPORT <span>void *get_module() 
</span>    <span>{
</span>        <span>// static(!) Php::Extension object that should stay in memory
</span>        <span>// for the entire duration of the process (that's why it's static)
</span>        <span>static Php::Extension extension("yourextension", "1.0");
</span>
        <span>// @todo    add your own functions, classes, namespaces to the extension
</span>
        <span>// return the extension
</span>        <span>return extension;
</span>    <span>}
</span><span>}  </span>
登入後複製
登入後複製
>我們只需要確保將骨架複製到PHP擴展的正確位置(在我的Ubuntu設置中,它應該為/usr/lib/php5/20121212,如上所示)。

然後,我們可以通過PHP -I |將擴展名驗證在CLI中加載。 GREP骨架,終端應顯示類似的東西:

>
<span>static Php::Extension extension("skeleton", "1.0"); // To be humble, we can change the version number to 0.0.1</span>
登入後複製
登入後複製

(回想一下skeleton.ini是我們修改的文件,其中包含擴展名= skeleton.so line。)

> 到目前為止,我們已經使用PHP-CPP進行了編譯並安裝了我們的第一個PHP擴展。當然,此擴展程序還沒有任何作用。現在,我們將創建第一個功能,以進一步了解建立PHP擴展的過程。

通過PHP-CPP開始PHP擴展開發“你好,泰勒”功能

我們創建的第一個功能將是“ Hello,World”的第一個功能。讓我們查看main.cpp的完整代碼:

>

>根據“註冊本機函數”上的PHP-CPP文檔,它支持四種類型的功能簽名:

在這種情況下,我使用第二個簽名,並且參數以數組形式(PHP功能)按值傳遞。

但是,在Helloworld中,我們專門使用了C型STD :: String來獲取第一個參數。 我們還使用C STD LIB來輸出一個熱情的消息。

在get_module()函數中,在聲明擴展變量後,我們添加了要導出的函數(helloworld()),並為php腳本(helloworld)分配一個名稱。

現在,讓我們編譯並安裝擴展程序。如果一切順利進行,新的骨架將復製到擴展名目錄。
<span>make && sudo make install</span>
登入後複製
登入後複製
登入後複製
登入後複製

我們可以編寫一個簡單的腳本來測試剛剛創建的函數:>

<span>cp -f skeleton.so /usr/lib/php5/20121212
</span><span>cp -f skeleton.ini /etc/php5/cli/conf.d</span>
登入後複製
請花一些時間來查看輸出:

>我們將回到以後觀察到的內容。

>函數參數通過參考

接下來,我們將看到另一個函數,該函數通過引用,swap()函數傳遞參數。在此功能中,我們還將嘗試指定參數及其類型的數量。

在main.cpp中,我們添加了另一個函數swap():

>

<span>sudo apt-get install php5-dev</span>
登入後複製
登入後複製
登入後複製
以及通過指定參數數量及其類型來導出功能:>

我們明確地說:
<span>make && sudo make install</span>
登入後複製
登入後複製
登入後複製
登入後複製

將有兩個參數(a和b);
    >
  • 應通過引用(而不是通過值); >通過
  • 它們應該是數字類型的。
  • >讓我們編譯並再次安裝更新的擴展程序,並編寫一些代碼片段,以查看此新功能的工作方式:>
交換($ a)將失敗。這是預期的和出乎意料的。預期的部分是我們需要兩個參數,只給出一個參數。但是,當調用函數交換並提示我們不夠的參數時,PHP不應該捕獲該錯誤嗎?

>

>第一個呼叫(交換($ a,$ b))顯示了預期的結果:20 | 10。該函數交換了兩個數字。
<span>extension=skeleton.so</span>
登入後複製
>

第二個通話是出乎意料的:我們告訴PHP我們要交換兩個數字!但是它只是忽略了第二個參數傳遞的是字符串,並且無論如何都進行交換!

好吧,從某種意義上說,仍然可以預期。 PHP並沒有真正區分數字類型和字符串類型。這種行為符合PHP標準。同樣,由於這種行為,我們沒有,也不能使用C內部類型作為功能(TEMP)中使用的臨時變量,而是使用PHP ::值作為變量類型。

第三個通話將起作用。第一個var_dump將顯示DateTime對象,第二個將顯示整數。這是某種程度上出乎意料的(至少對我來說)。畢竟,對象與數字/字符串完全不同。但是,在考慮到這種“互換”行為在PHP中也可行之後,它與PHP的奇怪之處相符。

>那麼,這是否意味著“類型”規範不會產生任何影響?並不真地。為了進一步闡述這一點,我們創建了第三個功能:>

我們這樣註冊了此功能:

測試代碼將是這樣的:

>
<span><span>#include <phpcpp.h></span>
</span>
<span>/**
</span><span> *  tell the compiler that the get_module is a pure C function
</span><span> */
</span><span>extern "C" {
</span>
    <span>/**
</span><span>     *  Function that is called by PHP right after the PHP process
</span><span>     *  has started, and that returns an address of an internal PHP
</span><span>     *  strucure with all the details and features of your extension
</span><span>     *
</span><span>     *  @return void*   a pointer to an address that is understood by PHP
</span><span>     */
</span>    PHPCPP_EXPORT <span>void *get_module() 
</span>    <span>{
</span>        <span>// static(!) Php::Extension object that should stay in memory
</span>        <span>// for the entire duration of the process (that's why it's static)
</span>        <span>static Php::Extension extension("yourextension", "1.0");
</span>
        <span>// @todo    add your own functions, classes, namespaces to the extension
</span>
        <span>// return the extension
</span>        <span>return extension;
</span>    <span>}
</span><span>}  </span>
登入後複製
登入後複製

>當我們通過正確的類類型(SampleClass)傳遞時,對SwapoBject()的第一個調用將起作用。第二個將失敗,顯示“可捕獲的致命錯誤:參數1傳遞給swapobject()必須是SampleClass的實例,是給定的另一個類別的實例...”。

<span>static Php::Extension extension("skeleton", "1.0"); // To be humble, we can change the version number to 0.0.1</span>
登入後複製
登入後複製
>上面的代碼段說明了類型限制的一個重要方面:標量類型聲明並未真正實現。 PHP以及PHP-CPP僅執行對像類型聲明。同樣,在PHP側並未真正執行參數的數量。

結論

在本文中,我們說明了準備PHP-CPP為我們的PHP環境工作的步驟。我們還討論了使用PHP-CPP(和C語義)創建PHP擴展的一些基本步驟。

>我們介紹了擴展項目文件,功能簽名,功能導出/註冊和功能參數類型。

>在下一篇文章中,我們將進一步詳細介紹PHP-CPP中的一些關鍵功能,並提供現實世界中的用例,展示了使用php-cpp的C類和名稱空間實現的使用。

>

>關於PHP擴展開發的常見問題(常見問題解答)

什麼是PHP-CPP,它與PHP有何不同?它提供了有據可查和用戶友好型類的集合,使C開發人員可以編寫PHP擴展名,而無需直接與Zend API合作的複雜性。與PHP是一種解釋的語言不同,PHP-CPP允許您以C(Comperied語言)編寫代碼。這可能會導致性能改進,因為編譯的代碼通常比解釋的代碼更快。

>如何在系統上安裝php-cpp?

在系統上安裝PHP-CPP需要從GitHub克隆PHP-CPP存儲庫。克隆後,導航到目錄並執行“ make”命令。構建過程完成後,使用“ Make install”命令安裝庫。請記住,您需要具有根特權來安裝庫。

>如何使用PHP-CPP? 創建基本的PHP擴展名,使用PHP-CPP創建PHP擴展程序涉及多個步驟。首先,您需要為擴展程序創建一個目錄並導航到其中。然後,為您的擴展程序創建一個“ makefile”和c源文件。 “ makefile”將包含構建擴展名的說明,而C源文件將包含用於擴展的實際代碼。編寫代碼後,您可以使用“ make”命令構建擴展名。

>如何調試我的php擴展名?

>調試PHP擴展程序可能會有些棘手,因為您''重新處理一種編譯的語言。但是,您可以使用GDB(GNU調試器)等工具進行調試。 GDB允許您設置斷點,逐步瀏覽代碼並檢查變量,在嘗試追踪錯誤時,這可能非常有用。

我可以使用php-cpp創建PHP 7的擴展名。

是的,PHP-CPP與PHP 7兼容。但是,您需要確保使用最新版本的PHP-CPP,因為較早的版本可能不支持PHP 7。

>我如何處理PHP-CPP中的異常?

php-cpp提供一個名為php ::異常的類,您可以用來從C代碼中拋出異常。這些例外可以像其他任何PHP例外一樣在您的PHP代碼中捕獲和處理。

>我可以使用PHP-CPP創建面向對象的擴展嗎?您可以在C代碼中定義類,然後可以在PHP代碼中使用這些類。這使您可以編寫易於維護的干淨,模塊化的代碼。

>如何從我的C代碼中調用PHP函數?

php-cpp提供了一個名為php :: call的類,您可以使用C代碼調用PHP功能。這使您可以利用PHP內置功能在擴展中的功能。

>我可以使用php-cpp創建與數據庫交互的擴展嗎? CPP創建與數據庫交互的擴展。但是,您需要使用C數據庫庫,因為PHP-CPP不提供任何內置數據庫功能。

>

>一旦您''如何分發我的php擴展名? VE構建了PHP擴展名,您可以通過將其包裝為PECL包裝來分配它。 PECL是PHP擴展的存儲庫,它提供了分發和安裝擴展的標準方法。

以上是通過PHP-CPP開始PHP擴展開發的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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