首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 內核開發實戰:從零建立 C 語言擴展(以字串重複函式為例)

     編輯:PHP 相關知識

PHP Extension 開發完整流程:ext_skel 骨架、C 實作、編譯安裝與驗證

為解決效能瓶頸或封裝 C 函式庫,開發 PHP 擴展是進階工程師必備技能。本文以實作 util_str_repeat(string, int) 為例,完整記錄 Ubuntu 環境下從產生骨架到安裝驗證的每一步。

1. 環境準備

# Ubuntu 20.04+
sudo apt update
sudo apt install -y php-dev build-essential autoconf automake libtool pkg-config
# php-dev 提供 phpize、php-config、headers

2. 取得 PHP 原始碼並產生骨架

# 下載對應版本原始碼(以 8.2 為例)
wget https://www.php.net/distributions/php-8.2.20.tar.gz
tar xzf php-8.2.20.tar.gz
cd php-8.2.20/ext

# 建立函式定義檔 util.def
echo 'string util_str_repeat(string str, long n)' > util.def

# 產生骨架
./ext_skel --extname=util --proto=util.def
cd util

3. 修改 config.m4 啟用 --enable-util

# config.m4
PHP_ARG_ENABLE(util, whether to enable util support,
[  --enable-util           Enable util support])

4. 實作 util.c 核心邏輯

// util.c 片段
PHP_FUNCTION(util_str_repeat) {
    char *str = NULL;
    size_t str_len;
    zend_long n;

    ZEND_PARSE_PARAMETERS_START(2, 2)
        Z_PARAM_STRING(str, str_len)
        Z_PARAM_LONG(n)
    ZEND_PARSE_PARAMETERS_END();

    if (n <= 0) {
        RETURN_EMPTY_STRING();
    }

    // 防止整數溢位
    if (str_len > 0 && n > (ZEND_SIZE_MAX / str_len)) {
        zend_error(E_ERROR, "Resulting string too large");
        return;
    }

    size_t result_len = str_len * n;
    char *result = emalloc(result_len + 1);
    char *ptr = result;

    while (n--) {
        memcpy(ptr, str, str_len);
        ptr += str_len;
    }
    *ptr = '\0';

    RETVAL_STRINGL(result, result_len);
    efree(result); // RETVAL_STRINGL 會複製,需手動釋放
}

5. 編譯安裝

cd /path/to/php-8.2.20/ext/util
phpize
./configure --enable-util
make -j$(nproc)
sudo make install
# 輸出:Installing shared extensions: /usr/lib/php/20220829/util.so

6. 啟用擴展

# 建立 ini 檔(PHP 8.2 模組目錄)
echo "extension=util.so" | sudo tee /etc/php/8.2/mods-available/util.ini
sudo phpenmod util
sudo systemctl restart php8.2-fpm  # 或 apache2

7. 驗證安裝

php -m | grep util
# 輸出: util

php -r 'for ($i=1;$i<=3;$i++) echo util_str_repeat("Test ", $i) . "\n";'
# 輸出:
# Test
# Test Test
# Test Test Test

8. 除錯技巧

  • gdb --args php test.php 進入 C 層除錯。
  • valgrind --tool=memcheck php test.php 偵測記憶體洩漏。
  • 開啟 zend.assertions=1、assert.exception=1 捕獲斷言。

9. 進階主題

主題關鍵點
類別與物件zend_class_entry, object_properties_init(), zend_object_std_init()
資源型別zend_register_list_destructors_ex(), ZEND_REGISTER_RESOURCE()
INI 設定PHP_INI_BEGIN(), STD_PHP_INI_ENTRY, OnUpdateLong
生命週期鉤子PHP_MINIT_FUNCTION, PHP_RINIT_FUNCTION, PHP_MSHUTDOWN_FUNCTION
測試.phpt 檔案,make test 執行

10. 參考資源

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved