|
|
# Win32 Hello World 示例
|
|
|
|
|
|
这个示例展示了如何使用 PHPX 编译器创建 Windows 程序,包括两种模式:
|
|
|
|
|
|
## 📁 示例文件
|
|
|
|
|
|
### 1. hello-console.php - 控制台版本(默认)
|
|
|
|
|
|
**特点:**
|
|
|
- ✅ 显示黑色控制台窗口
|
|
|
- ✅ 可以使用 `echo`、`print` 等控制台输出
|
|
|
- ✅ 可以显示消息框
|
|
|
- ✅ 适合命令行工具和调试
|
|
|
|
|
|
**编译命令:**
|
|
|
```bash
|
|
|
php ../../cli.php build --mode=bin hello-console.php
|
|
|
```
|
|
|
|
|
|
**运行效果:**
|
|
|
- 显示控制台窗口
|
|
|
- 输出文本信息到控制台
|
|
|
- 弹出消息框
|
|
|
|
|
|
---
|
|
|
|
|
|
### 2. hello-gui.php - GUI 版本(无控制台)
|
|
|
|
|
|
**特点:**
|
|
|
- ❌ 不显示控制台窗口
|
|
|
- ❌ `echo`、`print` 等控制台输出无效
|
|
|
- ✅ 只显示消息框等 GUI 元素
|
|
|
- ✅ 适合纯图形界面应用程序
|
|
|
|
|
|
**编译命令:**
|
|
|
```bash
|
|
|
php ../../cli.php build --mode=bin --no-console hello-gui.php
|
|
|
```
|
|
|
|
|
|
**运行效果:**
|
|
|
- 没有控制台窗口
|
|
|
- 直接弹出消息框
|
|
|
- 纯图形界面体验
|
|
|
|
|
|
---
|
|
|
|
|
|
### 3. debug-test.php - 调试测试程序
|
|
|
|
|
|
**特点:**
|
|
|
- ✅ 包含详细的日志记录
|
|
|
- ✅ 异常处理
|
|
|
- ✅ 逐步验证功能
|
|
|
- ✅ 用于排查 "Debug Assertion Failed" 问题
|
|
|
|
|
|
**编译命令:**
|
|
|
```bash
|
|
|
php ../../cli.php build --mode=bin --no-console debug-test.php
|
|
|
```
|
|
|
|
|
|
**使用方法:**
|
|
|
1. 编译并运行程序
|
|
|
2. 查看生成的 `debug-test.log` 文件
|
|
|
3. 根据日志定位问题
|
|
|
|
|
|
---
|
|
|
|
|
|
### 4. asan-test.php - AddressSanitizer 测试程序
|
|
|
|
|
|
**特点:**
|
|
|
- ✅ 演示 AddressSanitizer 的使用
|
|
|
- ✅ 包含各种内存操作测试
|
|
|
- ✅ 检测内存错误和泄漏
|
|
|
|
|
|
**编译命令:**
|
|
|
```bash
|
|
|
# Windows
|
|
|
php ../../cli.php build --mode=bin --sanitize=address --no-console asan-test.php
|
|
|
|
|
|
# Linux/macOS
|
|
|
php ../../cli.php build --mode=bin --sanitize=address,undefined asan-test.php
|
|
|
```
|
|
|
|
|
|
**使用方法:**
|
|
|
1. 编译带 sanitizer 的版本
|
|
|
2. 运行程序
|
|
|
3. 查看 `asan-test.log` 和控制台输出
|
|
|
4. 如果有内存错误,AddressSanitizer 会报告详细信息
|
|
|
|
|
|
---
|
|
|
|
|
|
### 5. debug-mode-test.php - 调试模式测试程序
|
|
|
|
|
|
**特点:**
|
|
|
- ✅ 演示 `--debug-info` 参数的使用
|
|
|
- ✅ 禁用优化,便于调试
|
|
|
- ✅ 生成完整的调试信息
|
|
|
- ✅ 支持 GDB、LLDB、Visual Studio 调试
|
|
|
|
|
|
**编译命令:**
|
|
|
```bash
|
|
|
# 启用调试模式(自动禁用优化 + 生成调试信息)
|
|
|
php ../../cli.php build --mode=bin --debug-info --no-console debug-mode-test.php
|
|
|
|
|
|
# 结合 AddressSanitizer
|
|
|
php ../../cli.php build --mode=bin --debug-info --sanitize=address --no-console debug-mode-test.php
|
|
|
```
|
|
|
|
|
|
**使用方法:**
|
|
|
1. 编译带调试信息的版本
|
|
|
2. 使用调试器加载程序
|
|
|
3. 设置断点、查看变量、单步执行
|
|
|
4. 查看 `debug-mode-test.log` 了解运行流程
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🔧 核心功能
|
|
|
|
|
|
### C++ 函数导出
|
|
|
|
|
|
本示例展示了如何将 C++ 函数导出为 PHP 函数:
|
|
|
|
|
|
1. **函数命名规范**:必须以 `php_` 为前缀
|
|
|
2. **类型要求**:只能使用 PHPX 类型(Int, String, Bool 等)
|
|
|
3. **Stub 声明**:必须在 `.stub.php` 文件中声明函数签名
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
C++ 实现 (`cpp-src/winapi.cc`):
|
|
|
```cpp
|
|
|
Int php_messagebox(Int hWnd, String text, String caption, Int uType) {
|
|
|
// 实现代码
|
|
|
}
|
|
|
```
|
|
|
|
|
|
PHP Stub 声明 (`cpp-src/winapi.stub.php`):
|
|
|
```php
|
|
|
function messagebox(int $hWnd, string $text, string $caption, int $uType): int {}
|
|
|
```
|
|
|
|
|
|
### 中文支持
|
|
|
|
|
|
#### C++ 层(消息框)
|
|
|
|
|
|
使用 `MultiByteToWideChar` 将 UTF-8 转换为 UTF-16:
|
|
|
|
|
|
```cpp
|
|
|
// Convert UTF-8 to UTF-16 for Windows API
|
|
|
int wtext_len = MultiByteToWideChar(CP_UTF8, 0, text.data(), -1, NULL, 0);
|
|
|
wchar_t* wtext = new wchar_t[wtext_len];
|
|
|
MultiByteToWideChar(CP_UTF8, 0, text.data(), -1, wtext, wtext_len);
|
|
|
|
|
|
int result = MessageBoxW((HWND)hWnd, wtext, wcaption, (UINT)uType);
|
|
|
|
|
|
delete[] wtext;
|
|
|
delete[] wcaption;
|
|
|
```
|
|
|
|
|
|
#### PHP 层(时区设置)
|
|
|
|
|
|
```php
|
|
|
// Set timezone to China (UTC+8)
|
|
|
date_default_timezone_set('Asia/Shanghai');
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 📖 详细文档
|
|
|
|
|
|
- [WINDOWS_GUI_GUIDE.md](./WINDOWS_GUI_GUIDE.md) - Windows GUI 程序完整指南
|
|
|
- [CHINESE_SUPPORT_GUIDE.md](./CHINESE_SUPPORT_GUIDE.md) - 中文支持详细说明
|
|
|
- [CPP_FUNCTION_EXPORT_GUIDE.md](./CPP_FUNCTION_EXPORT_GUIDE.md) - C++ 函数导出规范
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🚀 快速开始
|
|
|
|
|
|
### 编译控制台版本
|
|
|
|
|
|
```bash
|
|
|
# 进入示例目录
|
|
|
cd examples/win32-hello
|
|
|
|
|
|
# 编译
|
|
|
php ../../cli.php build --mode=bin hello-console.php
|
|
|
|
|
|
# 运行
|
|
|
.\hello-console.exe
|
|
|
```
|
|
|
|
|
|
### 编译 GUI 版本
|
|
|
|
|
|
```bash
|
|
|
# 进入示例目录
|
|
|
cd examples/win32-hello
|
|
|
|
|
|
# 编译(使用 --no-console 参数)
|
|
|
php ../../cli.php build --mode=bin --no-console hello-gui.php
|
|
|
|
|
|
# 运行
|
|
|
.\hello-gui.exe
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 💡 使用场景对比
|
|
|
|
|
|
| 场景 | 推荐模式 | 原因 |
|
|
|
|------|---------|------|
|
|
|
| 命令行工具 | 控制台模式 | 需要文本输出和输入 |
|
|
|
| 后台服务 | 控制台模式 | 需要日志输出 |
|
|
|
| 开发调试 | 控制台模式 | 便于查看调试信息 |
|
|
|
| 桌面应用 | GUI 模式 | 提供更好的用户体验 |
|
|
|
| 游戏 | GUI 模式 | 全屏或窗口化运行 |
|
|
|
| 工具软件 | GUI 模式 | 图形界面更友好 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## ⚙️ 编译选项说明
|
|
|
|
|
|
### --no-console 参数
|
|
|
|
|
|
- **作用**:隐藏控制台窗口,创建纯 GUI 应用程序
|
|
|
- **适用平台**:仅 Windows
|
|
|
- **链接选项**:添加 `/SUBSYSTEM:WINDOWS`
|
|
|
- **注意事项**:
|
|
|
- 控制台输出函数(echo、print 等)将无效
|
|
|
- 需要使用消息框或其他 GUI 元素进行输出
|
|
|
- 调试时建议使用控制台模式
|
|
|
|
|
|
### 其他常用选项
|
|
|
|
|
|
```bash
|
|
|
# 优化级别
|
|
|
php cli.php build -O2 app.php
|
|
|
|
|
|
# 指定输出文件名
|
|
|
php cli.php build -o myapp app.php
|
|
|
|
|
|
# 启用调试信息
|
|
|
php cli.php build --debug-info app.php
|
|
|
|
|
|
# 并行编译
|
|
|
php cli.php build -j 8 app.php
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🐛 常见问题
|
|
|
|
|
|
### Q: 为什么我的 echo 不显示?
|
|
|
|
|
|
A: 如果使用了 `--no-console` 参数,控制台被隐藏了。请改用消息框:
|
|
|
```php
|
|
|
messagebox(0, "你的消息", "标题", 0);
|
|
|
```
|
|
|
|
|
|
### Q: 如何调试没有控制台的程序?
|
|
|
|
|
|
A:
|
|
|
1. 使用消息框显示变量值
|
|
|
2. 写入日志文件:`file_put_contents('app.log', $msg, FILE_APPEND)`
|
|
|
3. 临时移除 `--no-console` 参数进行调试
|
|
|
4. 使用 [debug-test.php](./debug-test.php) 示例程序
|
|
|
5. 查看详细的 [DEBUG_GUIDE.md](./DEBUG_GUIDE.md)
|
|
|
|
|
|
### Q: 出现 "Debug Assertion Failed" 错误怎么办?
|
|
|
|
|
|
A: 这通常是由于 CRT 库冲突导致的。解决方法:
|
|
|
|
|
|
1. **重新编译**(编译器已自动添加 `/NODEFAULTLIB` 选项)
|
|
|
```bash
|
|
|
php ../../cli.php build --mode=bin --no-console your-app.php
|
|
|
```
|
|
|
|
|
|
2. **清理构建目录**
|
|
|
```bash
|
|
|
Remove-Item -Recurse -Force build/
|
|
|
php ../../cli.php build --mode=bin --no-console your-app.php
|
|
|
```
|
|
|
|
|
|
3. **使用调试测试程序**
|
|
|
```bash
|
|
|
php ../../cli.php build --mode=bin --no-console debug-test.php
|
|
|
.\debug-test.exe
|
|
|
# 查看 debug-test.log 文件
|
|
|
```
|
|
|
|
|
|
4. **查看详细调试指南**
|
|
|
- 参考 [DEBUG_GUIDE.md](./DEBUG_GUIDE.md)
|
|
|
- 使用 Visual Studio 调试器
|
|
|
- 使用 WinDbg
|
|
|
|
|
|
### Q: 中文显示乱码怎么办?
|
|
|
|
|
|
A: 确保:
|
|
|
1. 源文件使用 UTF-8 编码保存
|
|
|
2. C++ 中使用 `MultiByteToWideChar` 转换编码
|
|
|
3. 使用 `MessageBoxW` 而不是 `MessageBoxA`
|
|
|
4. 在 PHP 中设置正确的时区
|
|
|
|
|
|
### Q: 可以同时显示控制台和窗口吗?
|
|
|
|
|
|
A: 技术上可以,但不推荐。通常的做法是:
|
|
|
- 开发时使用控制台模式便于调试
|
|
|
- 发布时使用 GUI 模式提供更好的用户体验
|
|
|
|
|
|
---
|
|
|
|
|
|
## 📝 项目结构
|
|
|
|
|
|
```
|
|
|
win32-hello/
|
|
|
├── hello-console.php # 控制台版本示例
|
|
|
├── hello-gui.php # GUI 版本示例
|
|
|
├── debug-test.php # 调试测试程序(带日志)
|
|
|
├── debug-mode-test.php # 调试模式测试程序(--debug-info)
|
|
|
├── asan-test.php # AddressSanitizer 测试程序
|
|
|
├── main.php # 另一个示例文件
|
|
|
├── window.php # 窗口创建示例
|
|
|
├── cpp-src/
|
|
|
│ ├── winapi.cc # C++ 实现文件
|
|
|
│ └── winapi.stub.php # PHP Stub 声明
|
|
|
├── WINDOWS_GUI_GUIDE.md # GUI 程序指南
|
|
|
├── CHINESE_SUPPORT_GUIDE.md # 中文支持指南
|
|
|
├── CPP_FUNCTION_EXPORT_GUIDE.md # C++ 函数导出指南
|
|
|
├── DEBUG_GUIDE.md # 调试指南(重要!)
|
|
|
├── DEBUG_MODE_GUIDE.md # 调试模式使用指南
|
|
|
├── SANITIZER_GUIDE.md # AddressSanitizer 使用指南
|
|
|
├── MSVC_WARNINGS_SUPPRESSION.md # MSVC 警告屏蔽说明
|
|
|
└── README.md # 本文件
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 🔗 相关资源
|
|
|
|
|
|
- [PHPX 编译器文档](https://github.com/swoole/phpx)
|
|
|
- [Windows API 文档](https://docs.microsoft.com/en-us/windows/win32/api/)
|
|
|
- [MessageBoxW API](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw)
|
|
|
- [MultiByteToWideChar](https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar)
|
|
|
|