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

PHP 擴展開發入門完整指南:從環境建置到手工撰寫 Hello World

     編輯:PHP 相關知識

PHP 擴展以 C 語言撰寫,能突破使用者空間效能瓶頸、封裝 C 庫、實現語言層面無法做的底層操作。本文以 PHP 5.6/7.x 為例,完整記錄從源碼編譯、骨架生成、手工撰寫擴展到編譯驗證的全流程,並解析核心結構體與巨集用途。

第一階段:建置開發環境

# 1. 取得 PHP 源碼(以 7.4 為例)
git clone --depth=1 --branch PHP-7.4 https://github.com/php/php-src.git
cd php-src

# 2. 產生 configure 腳本
./buildconf --force

# 3. 編譯 PHP(開發模式:禁用所有擴展、開啟 debug、啟用 ZTS)
./configure --disable-all --enable-debug --enable-maintainer-zts
make -j$(nproc)

# 4. 建立別名方便測試
alias php-dev="$(pwd)/sapi/cli/php"

# 驗證
php-dev -v
php-dev -m   # 僅顯示 Core、date 等內建模組

第二階段:使用 ext_skel 產生骨架(快速入門)

cd ext
./ext_skel --extname=myext
cd myext

# 編輯 config.m4:取消註解 PHP_ARG_ENABLE 三行
# 返回源碼根目錄重新建置
cd ../..
./buildconf --force
./configure --disable-all --enable-myext --enable-debug --enable-maintainer-zts
make

# 驗證
php-dev -m | grep myext
php-dev -r 'echo confirm_myext_compiled("myext") . "\n";'

第三階段:手工撰寫擴展(深度理解)

目錄結構:

ext/myext2/
├── config.m4
├── php_myext2.h
└── myext2.c

1. config.m4 - 建置設定

PHP_ARG_ENABLE(myext2, whether to enable myext2 support,
[  --enable-myext2   Enable myext2 support])

if test "$PHP_MYEXT2" != "no"; then
  PHP_NEW_EXTENSION(myext2, myext2.c, $ext_shared)
fi

2. php_myext2.h - 標頭檔(規範命名)

#ifndef PHP_MYEXT2_H
#define PHP_MYEXT2_H

extern zend_module_entry myext2_module_entry;
#define phpext_myext2_ptr &myext2_module_entry

#define PHP_MYEXT2_VERSION "0.1.0"

PHP_FUNCTION(hello);  // 函式原型宣告

#endif

3. myext2.c - 核心實作

#include "php.h"
#include "php_myext2.h"

/* 函式表:暴露給 PHP 的函式列表 */
static const zend_function_entry myext2_functions[] = {
    PHP_FE(hello, NULL)   // 參數資訊暫用 NULL
    PHP_FE_END
};

/* 模組進入點結構體 */
zend_module_entry myext2_module_entry = {
    STANDARD_MODULE_HEADER,
    "myext2",                    // 模組名稱
    myext2_functions,            // 函式表
    NULL,                        // MINIT - 模組啟動
    NULL,                        // MSHUTDOWN - 模組關閉
    NULL,                        // RINIT - 請求啟動
    NULL,                        // RSHUTDOWN - 請求關閉
    NULL,                        // MINFO - phpinfo()
    PHP_MYEXT2_VERSION,          // 版本
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_MYEXT2
ZEND_GET_MODULE(myext2)  // 動態載入時需匯出此符號
#endif

/* hello 函式實作 */
PHP_FUNCTION(hello)
{
    php_printf("hello world!\n");
}

核心結構體與巨集解析

巨集/結構用途關鍵點
zend_function_entry函式表元素每個公開函式必須在此登記,以 PHP_FE_END 結尾
zend_module_entry模組資訊總表包含名稱、函式表、五大生命週期鉤子、版本、屬性旗標
PHP_FUNCTION(name)函式簽名展開實際展開為 void zif_name(INTERNAL_FUNCTION_PARAMETERS)
PHP_FE(name, arg_info)函式表項目第二參數為 zend_arg_info*,用於型別提示與反射
ZEND_GET_MODULE動態載入匯出符號僅當 COMPILE_DL_* 定義時編入(共享庫模式)
php_printf安全輸出到 PHP 輸出流等同 fprintf(php_output_get_stream(), ...),支援輸出緩衝

編譯與驗證(靜態編譯模式)

cd /path/to/php-src
./buildconf --force
./configure --disable-all --enable-myext2 --enable-debug --enable-maintainer-zts
make

# 測試
php-dev -m | grep myext2
php-dev -r 'hello();'   # 輸出: hello world!

進階主題路線圖

  1. 參數解析:zend_parse_parameters()、ZEND_PARSE_PARAMETERS_* 巨集、zend_arg_info 定型。
  2. 變數操作:zval 結構、引用計數、ZVAL_* 巨集、陣列/物件 API。
  3. 生命週期鉤子:MINIT/MSHUTDOWN(模組級)、RINIT/RSHUTDOWN(請求級)、資源註冊與清理。
  4. 物件導向:zend_class_entry、屬性/方法註冊、zend_object 手工實作。
  5. 記憶體管理:emalloc/efree、持久化分配、GC 整合。
  6. 除錯技巧:gdb --args php-dev ...、zend_dump_debug_info()、Valgrind 檢測洩漏。

PHP 擴展開發門檻較高,但掌握後能解決效能熱點、整合 C/C++ 生態、實現語言層無法達到的功能。建議從「手工撰寫最小擴展」開始,逐步深入 Zend Engine 內核機制。

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