本文目录导读:

我来详细介绍 PHP 扩展包(PHP Extension)的开发流程,包括从环境搭建到发布的完整过程。
开发环境准备
1 安装必要工具
# Ubuntu/Debian sudo apt-get install php-dev php-pear autoconf build-essential # CentOS/RHEL sudo yum install php-devel autoconf make gcc gcc-c++ # macOS brew install autoconf
2 获取 PHP 源码(可选)
# 下载对应版本的 PHP 源码 wget https://www.php.net/distributions/php-8.2.0.tar.gz tar -xzf php-8.2.0.tar.gz
扩展骨架生成
1 使用 ext_skel 工具
# 进入 PHP 源码的 ext 目录 cd php-8.2.0/ext # 生成扩展骨架 ./ext_skel --extname=myextension # 或者使用 pecl 工具 pecl gen-ext myextension
2 生成的目录结构
myextension/
├── config.m4 # 构建配置
├── config.w32 # Windows 配置
├── php_myextension.h # 头文件
├── myextension.c # 扩展主文件
├── myextension.php # 测试文件
├── tests/ # 测试目录
│ └── 001.phpt # 测试用例
└── package.xml # PECL 包配置
编写扩展代码
1 修改 config.m4
# 去掉 PHP_ARG_ENABLE 前的注释
PHP_ARG_ENABLE(myextension, whether to enable myextension support,
[ --enable-myextension Enable myextension support])
if test "$PHP_MYEXTENSION" != "no"; then
PHP_NEW_EXTENSION(myextension, myextension.c, $ext_shared)
fi
2 编写主头文件 php_myextension.h
#ifndef PHP_MYEXTENSION_H
#define PHP_MYEXTENSION_H
extern zend_module_entry myextension_module_entry;
#define phpext_myextension_ptr &myextension_module_entry
#define PHP_MYEXTENSION_VERSION "0.1.0"
#ifdef PHP_WIN32
# define PHP_MYEXTENSION_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
# define PHP_MYEXTENSION_API __attribute__ ((visibility("default")))
#else
# define PHP_MYEXTENSION_API
#endif
#ifdef ZTS
#include "TSRM.h"
#endif
#endif /* PHP_MYEXTENSION_H */
3 编写主实现文件 myextension.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_myextension.h"
/* 声明函数 */
PHP_FUNCTION(myextension_hello);
PHP_FUNCTION(myextension_add);
/* 参数信息 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_myextension_hello, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_myextension_add, 0, 0, 2)
ZEND_ARG_INFO(0, a)
ZEND_ARG_INFO(0, b)
ZEND_END_ARG_INFO()
/* 函数表 */
static const zend_function_entry myextension_functions[] = {
PHP_FE(myextension_hello, arginfo_myextension_hello)
PHP_FE(myextension_add, arginfo_myextension_add)
PHP_FE_END
};
/* 模块入口 */
zend_module_entry myextension_module_entry = {
STANDARD_MODULE_HEADER,
"myextension",
myextension_functions,
NULL, /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
NULL, /* MINFO */
PHP_MYEXTENSION_VERSION,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_MYEXTENSION
ZEND_GET_MODULE(myextension)
#endif
/* 实现 hello 函数 */
PHP_FUNCTION(myextension_hello)
{
RETURN_STRING("Hello from myextension!");
}
/* 实现 add 函数 */
PHP_FUNCTION(myextension_add)
{
zend_long a, b;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_LONG(a)
Z_PARAM_LONG(b)
ZEND_PARSE_PARAMETERS_END();
RETURN_LONG(a + b);
}
构建和编译
1 构建配置
# 在扩展目录执行 phpize ./configure --enable-myextension make
2 安装
make install
3 启用扩展
# php.ini 添加 extension=myextension.so
测试扩展
1 创建测试文件
// test.php <?php echo myextension_hello() . "\n"; echo myextension_add(5, 3) . "\n"; // 输出 8
2 编写 PHPT 测试
--TEST--
Test myextension_hello function
--SKIPIF--
<?php if (!extension_loaded('myextension')) die('skip extension not loaded'); ?>
--FILE--
<?php
echo myextension_hello();
?>
--EXPECT--
Hello from myextension!
运行测试:
make test
高级功能开发
1 定义类和对象
/* 定义类方法 */
PHP_METHOD(MyClass, __construct);
PHP_METHOD(MyClass, getName);
/* 类入口 */
zend_class_entry *myclass_ce;
/* 注册类 */
PHP_MINIT_FUNCTION(myextension)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "MyClass", myclass_methods);
myclass_ce = zend_register_internal_class(&ce);
return SUCCESS;
}
2 处理数组和资源
PHP_FUNCTION(myextension_process_array)
{
zval *arr;
HashTable *ht;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY(arr)
ZEND_PARSE_PARAMETERS_END();
ht = Z_ARRVAL_P(arr);
/* 遍历数组 */
zend_hash_internal_pointer_reset(ht);
while (zend_hash_has_more_elements(ht) == SUCCESS) {
zend_string *key;
zval *value;
zend_hash_move_forward(ht);
}
}
调试和优化
1 启用调试模式
# 编译时启用调试 CFLAGS="-g -O0" ./configure --enable-debug --enable-myextension make
2 使用 Valgrind
valgrind --tool=memcheck php test.php
3 内存管理建议
/* 正确使用内存 */
zend_string *str = zend_string_init("Hello", 5, 0);
php_printf("%s", ZSTR_VAL(str));
zend_string_release(str);
/* 安全处理资源 */
zend_resource *res = zend_register_resource(handle, resource_type);
发布流程
1 生成 PECL 包
# 更新 package.xml pecl package
2 提交到 PECL
# 创建账号并提交 pecl upload myextension-0.1.0.tgz
3 文档编写
// README.md # MyExtension ## 安装 ```bash pecl install myextension
使用
echo myextension_hello();
## 九、最佳实践
### 9.1 代码规范
- 遵循 PSR 标准编码风格
- 注释完整,便于维护
- 使用 PHP 官方命名约定
### 9.2 性能优化
```c
/* 使用 hashtable 加速 */
static HashTable myextension_global_data;
ZEND_INI_MH(update_myextension_setting)
{
/* 配置更新处理 */
}
/* 使用缓存 */
ZEND_BEGIN_MODULE_GLOBALS(myextension)
zend_long cache_size;
bool enabled;
ZEND_END_MODULE_GLOBALS(myextension)
3 兼容性考虑
- 支持 PHP 7.0+ 和 PHP 8.0+
- 提供 Windows 构建配置
- 使用条件编译处理版本差异
#if PHP_MAJOR_VERSION >= 8
/* PHP 8+ 的 API */
#else
/* PHP 7 的 API */
#endif
4 安全注意事项
- 使用
Z_PARAM_*宏进行参数验证 - 处理大整数溢出
- 防止内存泄漏
- 避免使用
eval等危险功能
CI/CD 集成
# GitHub Actions 示例
name: PHP Extension CI
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
php-version: ['7.4', '8.0', '8.1', '8.2']
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
tools: phpize
- name: Build
run: |
phpize
./configure --enable-myextension
make
- name: Test
run: make test
PHP 扩展开发是一个系统性的工程,从环境搭建、代码编写、调试测试到发布维护,需要掌握 C 语言、PHP 内部机制和构建工具等多方面知识,建议从简单的扩展开始,逐步增加复杂度,并充分利用官方文档和社区资源。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播