Windows 编译 PHP 扩展:从零到可用的完整教程
目标关键词:Windows 编译 PHP 扩展
在 Windows 环境下编译 PHP 扩展,很多人第一反应就是“麻烦、容易报错、环境难配”。确实,相比 Linux,Windows 下的 PHP 扩展编译门槛更高,但只要把环境搭对,流程其实是固定的。本文就围绕 Windows 编译 PHP 扩展 这个主题,按“问题分析 → 解决方案 → 注意事项”的结构,讲清楚从准备环境到成功生成 .dll 扩展文件的全过程,适合新手按步骤操作,也适合有经验的人直接对照排坑。
一、问题分析:为什么 Windows 下编译 PHP 扩展这么容易失败?
PHP 扩展本质上是一个动态库文件。
在 Linux 下通常是 .so,在 Windows 下则是 .dll。编译 PHP 扩展,不只是“装个编译器然后点一下编译”这么简单,它要求:
-
PHP 版本必须匹配
- 例如你用的是 PHP 8.1,就不能拿 PHP 7.4 的扩展源码直接编。
- 线程安全版(TS)和非线程安全版(NTS)也不能混用。
-
编译工具链必须匹配
- Windows 下通常要用 Visual Studio + MSVC。
- PHP 官方预编译包对应的编译器版本必须一致。
-
PHP 源码和头文件要齐全
- 编译扩展时需要
phpize类似的准备过程。 - Windows 下要使用官方 SDK、头文件、构建脚本。
- 编译扩展时需要
-
依赖库版本要一致
- 扩展如果依赖 OpenSSL、libcurl、zlib、libxml 等库,版本不一致就会报链接错误。
-
环境变量和路径容易出问题
cl.exe、nmake、cmake、php.exe、phpize所在目录找不到,编译会直接失败。
所以,Windows 下编译 PHP 扩展的核心不是“会不会写代码”,而是 环境、版本、工具链三者是否完全匹配。
二、解决方案:Windows 编译 PHP 扩展的标准流程
下面以常见的 Windows 开发环境为例,讲清楚完整流程。这里默认你是要编译一个 PHP 原生扩展,不是 Composer 包,也不是 PHP 脚本。
方案一:使用 PHP 官方 SDK + Visual Studio 编译
这是最常见、最正规的一种方式。
第一步:确认你的 PHP 版本和类型
先查看你当前 PHP 的信息,重点看这几个参数:
php -v
php -i | findstr "Thread Safety"
php -i | findstr "Architecture"
php -i | findstr "Compiler"
你需要确认:
- PHP 版本号:比如 8.1.12、8.2.10
- 线程安全:TS 还是 NTS
- 架构:x64 还是 x86
- 编译器:例如 Visual C++ 2019 / 2022
这些信息非常重要,因为扩展必须和 PHP 主程序匹配。
第二步:安装 Visual Studio 编译环境
建议安装:
- Visual Studio 2022
- 勾选 使用 C++ 的桌面开发
- 同时安装:
- MSVC 编译工具
- Windows 10/11 SDK
- CMake 工具(有些项目会用到)
如果你只想轻量一点,也可以安装:
- Build Tools for Visual Studio 2022
安装后,打开:
- x64 Native Tools Command Prompt for VS 2022
这个命令行窗口里已经帮你配置好了 cl.exe、nmake 等编译工具环境。
第三步:下载匹配的 PHP 开发包
不要直接拿你本机的 PHP 安装目录硬编,最好下载对应版本的开发包。
你需要准备:
- PHP 对应版本的源码或开发包
- 和当前 PHP 版本一致的头文件
- 匹配的
phpize/ build 文件
如果你在编译第三方扩展,通常扩展源码目录里会带:
config.w32php_*.h*.c*.m4或 Windows 平台构建文件
Windows 下更常见的是 config.w32 方案。
第四步:准备扩展源码
假设你要编译的扩展目录如下:
myext/
├─ config.w32
├─ php_myext.h
├─ myext.c
├─ myext_arginfo.h
├─ package.xml
└─ ...
你需要确认这个扩展本身支持 Windows 编译。
如果源码只写了 Linux 的 config.m4,那在 Windows 上不能直接用,通常需要额外适配 config.w32。
第五步:配置 PHP 扩展编译环境
Windows 下常见的做法是使用 php-sdk-binary-tools 或者官方推荐的构建环境。
一般流程是:
- 安装 PHP SDK 工具包
- 设置源码目录
- 设置目标 PHP 版本目录
- 运行
buildconf或相关脚本 - 生成编译项目
- 使用
nmake编译
不同 PHP 版本和扩展项目,脚本略有差异,但核心思路一致。
第六步:编译扩展
如果扩展项目已经适配好 Windows,常见步骤会类似下面这样:
方式 1:使用 configure / nmake 流程
进入扩展源码目录后,运行类似命令:
phpize
configure --enable-myext
nmake
nmake test
但要注意:
Windows 原生环境下不一定有标准的 phpize,这更常见于类 Unix 环境。
在 Windows 下,很多时候是通过 config.w32 + buildconf + nmake 完成。
方式 2:使用 config.w32
如果扩展目录下有 config.w32,通常会这样操作:
- 打开开发者命令行
- 进入 PHP 源码或扩展构建环境
- 执行生成配置
- 执行编译命令
常见结果是生成:
php_myext.dll
编译成功后,把这个 DLL 放到 PHP 的 ext 目录。
第七步:启用扩展
编译完成后,编辑 php.ini,加入:
extension=myext.dll
如果扩展 DLL 放在 ext 目录下,通常这样写就行。
如果 DLL 不在默认扩展目录,可以写绝对路径:
extension="D:\php\ext\myext.dll"
然后重启 Web 服务或命令行重新打开 PHP,检查是否加载成功:
php -m
或者:
php -i | findstr myext
如果能看到扩展名称,说明加载成功。
三、实战示例:编译一个简单的 PHP 扩展
下面给一个更贴近实战的思路,方便理解整个过程。
示例目标
编译一个名为 myext 的 PHP 扩展,功能是提供一个简单函数:
echo myext_hello();
返回:
Hello Windows PHP Extension
第一步:准备扩展代码
扩展代码一般包括:
- 扩展入口
- 函数声明
- 模块初始化
- 头文件
如果你是自己写扩展,最少要确保:
- 有正确的函数签名
- 有
MINIT、MSHUTDOWN、RINIT、RSHUTDOWN - 导出模块信息
第二步:确认 PHP API 版本一致
编译扩展时,最容易踩坑的是 API 不匹配。
例如:
php8ts.dll对应 TS 版本php8.dll对应 NTS 版本
如果你拿 TS 版 PHP 去加载 NTS 版扩展,或者反过来,通常会直接报错:
The specified module could not be foundUnable to load dynamic libraryPHP Startup: Unable to load dynamic library
这类错误不一定是文件真的找不到,很多时候是 依赖或版本不匹配。
第三步:检查依赖 DLL
如果扩展依赖其他库,比如:
libssl-3-x64.dlllibcrypto-3-x64.dllzlib1.dlllibxml2.dll
这些 DLL 也必须存在于:
- PHP 安装目录
- 系统 PATH
- 扩展 DLL 同目录
否则扩展加载时会失败。
四、常见报错与排查方法
Windows 编译 PHP 扩展,最常见的问题基本就这些。
1. cl.exe 找不到
原因
没有打开 Visual Studio 开发者命令行,或者 C++ 工具没有安装完整。
解决方法
- 打开 x64 Native Tools Command Prompt for VS 2022
- 检查安装了 使用 C++ 的桌面开发
- 在命令行执行:
cl
如果能显示版本信息,说明环境正常。
2. nmake 不是内部或外部命令
原因
没有加载 VS 编译环境。
解决方法
- 使用 Visual Studio 提供的开发者命令行
- 或者手动执行环境脚本后再编译
3. Unable to load dynamic library
原因
常见有以下几种:
- DLL 不是当前 PHP 版本编译的
- TS/NTS 不匹配
- x64/x86 不匹配
- 依赖 DLL 缺失
- 扩展名写错
php.ini路径配置错误
解决方法
逐项检查:
php -v看版本php -i | findstr "Thread Safety"看 TS/NTSphp -i | findstr "Architecture"看架构- 检查 DLL 是否放在正确目录
- 用
Dependencies工具查看缺失依赖
4. 编译时报头文件找不到
原因
PHP 开发头文件路径没配好,或者源码目录不完整。
解决方法
确认包含以下内容:
php.hzend.hext/standard/info.h- 对应扩展依赖头文件
如果是第三方扩展,确保源码树完整,不要只下载了单个 .c 文件。
5. 链接错误、符号未定义
原因
函数声明和实现不一致,或者调用了未正确导出的库。
解决方法
- 检查函数原型
- 确认导出宏是否正确
- 检查链接库是否匹配 32/64 位
- 检查是否用了不兼容的编译选项
五、推荐的新手方案:先用现成扩展,再考虑自己编译
如果你是电脑小白,建议先按这个顺序来:
第一步:先找现成 DLL
很多 PHP 扩展在 Windows 下已经有预编译版本,比如:
- redis
- xdebug
- imagick
- mysqli
- grpc
- ssh2
如果官方或第三方已经提供了适配你 PHP 版本的 DLL,优先直接下载使用。
第二步:确认匹配关系
下载时重点看:
- PHP 版本
- TS/NTS
- x64/x86
- VC 编译版本
第三步:再考虑自己编译
只有在以下情况才建议自己编译:
- 没有现成版本
- 需要修改扩展源码
- 需要适配特殊库
- 想学习 PHP 扩展开发
这样能少踩很多坑。
六、进阶方案:用 Docker 或 WSL 降低编译难度
如果你的目标不是“必须在 Windows 原生编译”,而是“把扩展跑起来”,那可以考虑更省事的方案。
方案 A:WSL
在 Windows 上安装 WSL,然后在 Linux 环境下编译 PHP 扩展。
优点是:
- 编译环境更接近 Linux 原生流程
phpize、configure、make更顺手- 适合很多开源扩展
缺点是:
- 最终生成的是 Linux 的
.so - 不能直接给 Windows PHP 用
方案 B:Docker
如果你只是为了开发、测试、部署到 Linux 服务器,可以直接用 Docker 搭环境。
优点:
- 环境干净
- 依赖隔离
- 重现性好
缺点:
- 同样不直接生成 Windows 的
.dll
如果你的目标是 Windows 本机 PHP 环境,那还是得走 Windows 原生编译链。
七、注意事项:编译成功前必须检查的细节
下面这些点,建议你动手前先确认。
1. PHP 版本必须完全一致
不要只看大版本,比如“都是 PHP 8”,这还不够。
最好精确到小版本,尤其是:
- 8.1.x
- 8.2.x
- 8.3.x
很多扩展对小版本 API 也有要求。
2. TS 和 NTS 不能混用
这是 Windows 下最常见的坑之一。
- TS:线程安全版
- NTS:非线程安全版
Apache 模式下很多情况下要用 TS,
而 IIS/FastCGI 或命令行常见 NTS。
3. 32 位和 64 位必须一致
x86 的 PHP 只能加载 x86 扩展,
x64 的 PHP 只能加载 x64 扩展。
这条看起来简单,但非常容易忽略。
4. 运行库要匹配
Windows 扩展经常依赖 Visual C++ 运行库。
如果系统缺少对应版本的 VC Runtime,也会导致扩展加载失败。
建议安装:
- Visual C++ Redistributable 2015–2022 x64
- 如有需要再装 x86 版本
5. 用文本编辑器检查 php.ini
很多人扩展明明编译好了,却因为 php.ini 写错导致没加载。
正确做法:
- 确认
extension_dir指向正确目录 - 扩展名写对
- 注释符号没有保留
- 修改后重启服务
示例:
extension_dir="D:\php\ext"
extension=myext.dll
八、排错顺序:遇到问题先按这个流程查
如果你编译或加载失败,建议按下面顺序排查:
-
确认 PHP 版本
php -v
-
确认线程安全
php -i | findstr "Thread Safety"
-
确认架构
php -i | findstr "Architecture"
-
确认编译器
clnmake
-
确认 DLL 位置
- 是否放在
ext目录
- 是否放在
-
确认
php.ini配置extension_dirextension=xxx.dll
-
检查依赖 DLL
- 使用 Dependencies 工具查看缺失项
-
检查日志
- PHP 错误日志
- Web 服务器日志
- Windows 事件查看器
九、适合新手的最稳妥建议
如果你第一次接触 Windows 编译 PHP 扩展,最稳妥的做法是:
- 先确认你本机 PHP 版本、TS/NTS、x64/x86
- 安装 Visual Studio 2022 和 C++ 组件
- 找到和 PHP 完全匹配的扩展源码或预编译包
- 先尝试加载现成 DLL,确认环境无误
- 再进入源码编译
- 编译后立刻用
php -m验证 - 如果失败,优先查版本和依赖,不要先怀疑代码
这样能把排错时间缩到最短。
十、总结
Windows 编译 PHP 扩展的关键,不是“会不会写扩展代码”,而是 环境、版本、架构、运行库、依赖 这五件事必须全部匹配。只要把这些基础工作做扎实,编译流程其实是很稳定的。
最核心的几条记住就够了:
- PHP 版本一致
- TS/NTS 一致
- x64/x86 一致
- Visual Studio 编译环境准备好
- 依赖 DLL 不能缺
php.ini配置要正确
只要按步骤走,Windows 下编译 PHP 扩展并没有想象中那么难。真正难的地方,往往不是编译命令本身,而是前期环境没对齐。

还没有评论,来说两句吧...