TypePHP对象存储三模型:Native Binary编译下Zend Object、PHPX Box与Native Class的完整边界指南
【免费下载链接】typephpCompile PHP to Native Binaries项目地址: https://gitcode.com/GitHub_Trending/ty/typephp
TypePHP是一款将 PHP 编译为 Native Binary(原生二进制)的 PHP 编译器。为了同时兼顾「PHP 兼容性」和「C++ 级性能」,它的运行时中并存着三套对象存储与传递模型:Zend Object、PHPX Box和Native Class。这篇文章用通俗的方式讲清楚三套模型分别存什么、怎么传、边界在哪里,帮助你在项目中快速做对选择。
🧭 一句话结论:三套模型解决三类冲突问题
- Zend Object—— 完整保留 PHP 动态对象语义,是与 ZendVM 生态全面互操作的方式;
- PHPX Box—— 把无法完整写进 PHP 类型声明的 C++ 类型(泛型容器、高精度数值)包装成不透明的值载体;
- Native Class—— 为静态可知的业务对象提供接近 C/C++ 的固定布局与裸指针调用,追求极致性能。
TypePHP 官方明确接受三套模型长期共存,不以「统一对象表示」为目标——这是一次有意的架构选择,而不是历史遗留。
在 Minecraft Demo 中,PHP 负责世界生成和角色移动,C++ 负责窗口与渲染——这类 PHP + C++ 混合架构的项目,正是最需要选对对象模型的场景。
📋 三模型快速对比:一张表看懂核心差异
| 维度 | Zend Object | PHPX Box | Native Class Object |
|---|---|---|---|
| 典型值 | 普通 PHP class 实例 | Std Container、BigInt、Decimal 等 | #[Native] class实例 |
| 主要表示 | zend_object/ zval | zend_resource+php::Box * | Native Heap 中的 C++ struct + 裸指针 |
| 生命周期 | Zend 引用计数 + 循环 GC | resource 析构回调调用 Box destructor | Wren 风格精确 mark-sweep GC |
| 参数传递 | 复制句柄并调整引用计数 | php::Var携带 resource | 具体NativeClass *按值传递,不加 RC |
| 动态 PHP 互操作 | 完整 | 有限(不透明 resource) | 不可进入 ZendVM value 边界 |
| 核心目标 | PHP 兼容性 | 携带 C++ 泛型 / 扩展值 | 极致静态性能 |
完整对照与编译器实现约束见官方设计文档:docs/zh-cn/OBJECT_STORAGE_AND_PASSING_MODELS.md
🧩 Zend Object:完整 PHP 动态语义的唯一载体
普通 class 会注册到 ZendVM,实例由zend_object表示。它的行为对 PHP 用户来说完全无感:
- 赋值和传参复制的是「对象句柄」,不是对象实体,并遵循 Zend 引用计数;
- 循环引用由 Zend GC 扫描回收;
- 对象可以自由进入 PHP 数组、Closure、Generator、Reflection、序列化等一切动态场景。
为什么不可替代:只有 Zend Object 能完整承载 class entry、对象 handlers、可见性、Reflection 和动态分派。换成 Box 会丢失这些元数据,换成 Native Object 则会失去 ZendVM 可见性。
所以规则很简单:普通 PHP class 始终使用 Zend Object,编译器只能优化调用,不能改变它的对象模型。对象的创建流程与默认值初始化细节见 docs/zh-cn/OBJECT_CREATION.md。
📦 PHPX Box:C++ 泛型类型的不透明载体
Box 解决一个很实际的问题:PHP 函数签名表达不了 C++ 泛型类型。比如std::vector<int>和std::map<string, App\User>,PHP 参数最多只能声明一个非泛型类名,容器种类、key/value 类型、数组维度都没地方放。
Box 的做法是把 C++ 多态基类注册为 Zend resource,由php::Var携带,传递链是:zval (IS_RESOURCE) → zend_resource → php::Box * → 具体 C++ 值。
当前主要使用者:
StdContainerBox:std::vector<T>、std::array<T, N>、map 类容器;- BigInt、BigFloat、Decimal 等高精度数值。
Box 的边界同样清晰:
- Zend GC 只看得见 resource,不会扫描 Box 内部的 C++ 对象图;
- 不提供 PHP class 的方法表、属性表、继承和 Reflection;
- 不适合构建需要跨 Zend/Box 双向追踪的任意循环对象图。
Box 适合数值、容器这类边界明确的扩展值,Std 容器的完整使用规则见 docs/zh-cn/STD_CONTAINERS.md。
Ocean Demo 里,波浪计算、昼夜循环、天气切换等游戏逻辑全部用 PHP 编写并编译进同一个 Native Binary——这类计算密集型项目的大量容器与高精度运算,正是 Box 模型的主战场。
⚡ Native Class:固定布局、裸指针调用的极致热路径
#[Native]class 不走 ZendVM:不注册 Zend class、不生成对象 handlers、没有 zval 表示。每个对象是 Native Heap 中固定布局的 C++ struct,局部变量和参数直接保存具体裸指针。
你能得到什么:
- 对象句柄只占一个机器字,传递时不增加引用计数;
- 字段固定偏移访问,C++ 编译器可以内联和去虚化;
- 循环引用由 tracing GC 精确回收,
__destruct()在 Native finalization 中执行。
代价(边界清单):
- 参数和返回值必须显式声明具体 Native class(或受支持的 nullable 形式);
- 不能传给 PHP/ZendVM 函数、Closure 或动态 callable;
- 不能存入 PHP 数组、普通对象属性或
mixed变量; - 进入 PHP API 前必须显式
toArray()式复制数据,副本不保留 Native 对象身份。
也就是说,Native Class 是一种「显式选择」的高性能模式:你必须声明它并接受功能限制。设计细节见 docs/zh-cn/NATIVE_CLASS_OBJECT.md,编译器实现位于 src/NativeClass/。
🚫 为什么不能统一?三条边界一次讲透
最常见的疑问是:为什么不把对象模型统一成一套?TypePHP 的回答是——任何统一方向都会牺牲核心能力:
| 如果统一为 | 会失去什么 |
|---|---|
| 全部 Zend Object | Native Class 失去接近 C/C++ 的热路径;Std Container 要为海量模板组合设计运行时 class 体系 |
| 全部 Box | Zend GC 看不见 Box 内部对象图,既不能替代动态元数据,也提供不了裸指针热路径 |
| 全部 Native 指针 | 普通 PHP 对象失去 Reflection、动态属性和扩展互操作;泛型类型无法写入 PHP 签名,产生不安全的类型擦除 |
TypePHP 还明确不增加自动桥接:三套模型之间不做隐式对象身份转换,自动装箱/拆箱会隐藏分配、复制和 GC root 变化,让编译器边界不再可靠。允许的跨模型转换必须显式且语义明确——容器转 PHP 数组是复制数据,toArray()是用户定义的实体复制,高精度类型显式转换产生新的 PHP 标量值。
✅ 如何选型:一张对照表做出决定
| 你的场景 | 推荐模型 | 原因 |
|---|---|---|
| 普通业务类,需要 Reflection / 序列化 / 动态调用 | Zend Object | 唯一具备完整 PHP 语义的模型 |
| 泛型容器、高精度数值计算 | PHPX Box | 签名表达不了泛型类型,Box 是天然载体 |
| 少量字段、静态可知的热路径业务对象 | Native Class | 固定布局 + 裸指针调用,性能接近 C++ |
需要把对象传给动态 callable 或存进mixed | 只能 Zend Object | Box 互操作有限,Native 无法跨界 |
官方文档还强调一条核心原则:先根据静态类型确定对象模型,再选择代码生成路径,不得在运行时三者之间猜测——这也是三套模型 ABI 互不混用的根本原因。
📚 延伸阅读
- 三模型总体设计与编译器约束:docs/zh-cn/OBJECT_STORAGE_AND_PASSING_MODELS.md
- Native Class 设计与实现:docs/zh-cn/NATIVE_CLASS_OBJECT.md
- Std 容器规则:docs/zh-cn/STD_CONTAINERS.md
- Zend Object 创建与默认值初始化:docs/zh-cn/OBJECT_CREATION.md
- 混合架构示例:examples/minecraft-demo/README.md、examples/ocean-demo/README.md
- Native Class 编译器实现:src/NativeClass/
【免费下载链接】typephpCompile PHP to Native Binaries项目地址: https://gitcode.com/GitHub_Trending/ty/typephp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考