本教程在 Ubuntu 12.04 (PHP 5.3.10) 環境下,演示從源碼簽出到編譯安裝一個簡單 PHP C 擴展的完整流程,適合理解 PHP 內核擴展開發基礎。
# 安裝構建工具
sudo apt-get install build-essential autoconf libtool pkg-config
# 安裝 PHP 開發頭文件 (提供 phpize, php-config)
sudo apt-get install php5-dev
# 安裝 SVN (獲取 PHP 源碼)
sudo apt-get install subversion
# 簽出 PHP 5.3.10 分支
svn checkout https://svn.php.net/repository/php/php-src/branches/PHP_5_3_10/ php-src
cd php-src
現代 PHP 源碼已遷移至 GitHub:git clone https://github.com/php/php-src.git --branch PHP-8.2
cd ext
./ext_skel --extname=myext
cd myext
生成結構:
myext/
├── config.m4 # 構建配置
├── config.w32 # Windows 構建配置
├── myext.c # 核心 C 代碼
├── php_myext.h # 頭文件
├── tests/ # 測試腳本
└── myext.php # 測試入口
編輯 config.m4,取消註釋 PHP_ARG_WITH 區塊:
dnl 原始 (註釋狀態):
dnl PHP_ARG_WITH(myext, for myext support,
dnl Make sure that the comment is aligned:
dnl [
dnl --with-myext Include myext support
dnl ])
# 修改為 (去掉 dnl):
PHP_ARG_WITH(myext, for myext support,
Make sure that the comment is aligned:
[
--with-myext Include myext support
])
編輯 myext.c,實現簡單函數:
/* {{{ proto string myext_hello(string name)
Return greeting message */
PHP_FUNCTION(myext_hello)
{
char *name = NULL;
size_t name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
return;
}
char *greeting;
spprintf(&greeting, 0, "Hello %s from myext!", name);
RETURN_STRING(greeting);
}
/* }}} */
/* 函數條目表 */
const zend_function_entry myext_functions[] = {
PHP_FE(myext_hello, NULL)
PHP_FE_END
};
/* 模塊條目 */
zend_module_entry myext_module_entry = {
STANDARD_MODULE_HEADER,
"myext",
myext_functions,
NULL, NULL, NULL, NULL, NULL,
"0.1.0",
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE(myext)
cd /path/to/php-src/ext/myext
# 1. 生成 configure 腳本
phpize
# 輸出: Configuring for: PHP Api Version: 20090626 ...
# 2. 配置
./configure --with-php-config=/usr/bin/php-config
# 或指定 PHP 路徑: ./configure --with-php-config=/usr/local/php/bin/php-config
# 3. 編譯
make
# 4. 安裝 (需 root)
sudo make install
# 輸出: Installing shared extensions: /usr/lib/php5/20090626+lfs/myext.so
# 創建 ini 文件
echo "extension=myext.so" | sudo tee /etc/php5/conf.d/myext.ini
# 重啟 Web 服務器
sudo service apache2 restart
# 或 php-fpm: sudo service php5-fpm restart
# CLI 驗證
php -m | grep myext
php -r "echo myext_hello('World');"
# 輸出: Hello World from myext!
# phpinfo() 頁面查看 myext 區塊
| 問題 | 解決 |
|---|---|
phpize: not found | 安裝 php5-dev / php-dev |
configure: error: Cannot find php-config | 指定路徑 ./configure --with-php-config=... |
編譯報錯 zend_API.h: No such file | 確認 PHP 開發包已安裝,路徑正確 |
| 模塊加載失敗 | 檢查 php -m、php -i | grep extension_dir、ldd myext.so 依賴 |
| 函數未定義 | 確認 zend_function_entry 註冊、PHP_FE 宏正確、重啟了服務器 |
ZEND_PARSE_PARAMETERS_* 宏簡化參數解析ZEND_STRING、ZEND_ARRAY 等新 APIC 擴展能突破 PHP 性能瓶頸,但維護成本高,建議優先優化 PHP 代碼、引入 Swoole/RoadRunner、或使用 FFI (PHP 7.4+) 調用共享庫。