vphp
vphp
Documentation entry:
- overview: docs/OVERVIEW.md
- docs index: docs/README.md
如果
vslim
vhttpd
vphp
- V 代码怎么导出成 PHP class / function / enum / interface
- V 代码怎么调用 PHP / Zend 世界里的函数、类、对象、属性、常量
- 两边对象、
ZVal、所有权、生命周期怎么桥接
一句话定义:
-
vphp= Zend Binding for Vlang
如果再产品化一点:
-
vphp是让 V 成为 PHP 实现语言之一的桥接层
它解决什么问题
vphp
它的目标更接近:
- 让 V 成为 PHP 的实现语言之一
- 让 V 类型能导出到 PHP
- 让 V 运行时能安全调用 Zend userland / internal symbols
- 让上层框架和运行时可以直接复用这套桥接能力
所以它既有:
-
V -> PHPinterop - 也有
V -> Zend export
vphp vs PHP-CPP vs ext-php-rs
从官方文档和指南看,三者都在解决“用非 C 语言开发 PHP 扩展”这个问题,但能力边界并不一样。
| 维度 | vphp | PHP-CPP | ext-php-rs |
|---|---|---|---|
| 主要语言 | V | C++ | Rust |
| 核心定位 | 语言桥接层 + Zend 导出层 + 上层框架基础设施 | C++ 友好的 PHP 扩展开发库 | Rust 的 Zend API binding + 宏/trait 抽象 |
| PHP 函数导出 | 有 | 有 | 有 |
| PHP 类导出 | 有 | 有 | 有 |
| interface / trait / enum 导出 | 有,且是当前设计重点 | 官方文档重点在 class / object / method,trait / enum 不是首页能力 | class / interface 支持明确;trait / enum 在官方入门材料里不是首屏能力 |
| attributes / 元信息导出 | 有,支持 PHP 8 class attributes | 官方文档未把 attributes 作为核心能力强调 | 宏和 doc comments 支持明确,attributes 能力偏 Rust 宏驱动 |
| 统一值桥接抽象 |
ZVal
*ZBox
|
Php::Value
Php::Parameters |
IntoZval
FromZval
ZBox
ZendObject |
| request / persistent 生命周期模型 | 显式,
Borrowed
RequestOwned
PersistentOwned
|
有扩展回调,但对象所有权模型更偏 C++ 开发者自行管理 | 依赖 Rust 类型系统、trait 与 module lifecycle hook |
| request startup / shutdown hook | 有,且可由框架层显式 request_scope 控制 | 有,
onRequest()
onIdle()
onStartup()
onShutdown() |
有,
ModuleBuilder
|
| 命名空间 / 模块注册 | 有 | 有,
Php::Namespace
Php::Extension |
有,
#[php_module]
ModuleBuilder |
| 设计重心 | 既做 interop,也做“V 导出 PHP 类型系统” | 让 C++ 写扩展更顺手 | 让 Rust 写扩展更安全、更符合 Rust 习惯 |
| 对上层框架的适配 | 强,直接为
vslim
vhttpd
|
更偏通用扩展开发 | 更偏通用扩展开发 |
| 最适合的场景 | 想把 V 当作 PHP 实现语言之一,且需要语言桥接、导出、运行时协同时 | 已有 C++ 代码库,要快速暴露给 PHP | 希望利用 Rust 安全性和生态来写 PHP 扩展 |
一个简化判断:
- PHP-CPP 更像 “C++ 友好的扩展 SDK”
- ext-php-rs 更像 “Rust 风格的扩展 binding / macro 框架”
-
vphp更像 “把 V 接进 Zend 世界,并支撑上层 V 驱动 PHP 运行时的桥接层”
延伸阅读:
- PHP-CPP 文档:函数、类、常量、命名空间、扩展回调
- ext-php-rs 文档:
#[php_module]、 ModuleBuilder、 #[php_class]、 RegisteredClass - 仓库内更细的 ownership 对比:
官方参考:
- PHP-CPP 首页与文档目录:
- ext-php-rs 指南与 API:
What vphp Already Does
当前最值得关注的能力是:
- 统一的
ZValinterop 入口 -
RequestBorrowedZBox/ RequestOwnedZBox/ PersistentOwnedZBox所有权模型 - V 导出 PHP class / trait / interface / enum
- PHP 8 class attribute 导出
- compiler/export pipeline
Core Areas
1. PHP Interop
这是
vphp
核心对象分两层:
-
ZVal -
*ZBox
其中:
-
ZVal负责底层 Zend interop 能力 -
*ZBox负责应用层生命周期与 ownership 语义
V 侧通过
ZVal
- 调 PHP 函数
- 构造 PHP 对象
- 调实例方法 / 静态方法
- 读写属性 / 静态属性
- 取类常量
- 把结果转回 V 标量或 V 导出对象
更细文档:
2. PHP-facing OOP Export
这层回答“V 代码怎么导出成 PHP 类体系”。
当前重点能力包括:
-
@[php_class] -
@[php_trait] -
@[php_method] -
@[php_interface] -
@[php_enum] -
@[php_abstract] -
@[php_implements: 'InterfaceName'] -
@[php_extends: 'ParentClass'] -
@[php_const: shadow_const] -
@[php_static: shadow_static] -
@[php_attr: 'AttributeName(...)']
当前约束:
-
@[php_implements: '...']支持同扩展导出的接口,也支持 userland/autoload 接口;后者会自动在生成的 vphp_ext_auto_startup()里注册 runtime binding -
@[php_extends: '...']只支持同扩展导出的类或 PHP internal class;不支持 userland 父类,违规会在编译期直接报错
Lifecycle hooks:
- module init:
vphp_ext_auto_startup()then vphp_ext_startup() - module shutdown:
vphp_ext_shutdown()then vphp_ext_auto_shutdown() - request init:
vphp_ext_request_auto_startup()then vphp_ext_request_startup() - request shutdown:
vphp_ext_request_shutdown()then vphp_ext_request_auto_shutdown()
其中:
-
auto_*由编译器/运行时保留给自动生成逻辑 - 不带
auto_的 hook 留给扩展作者自定义逻辑
最小示例:
module main
__global (
ext_request_boots int
)
@[export: 'vphp_ext_startup']
fn vphp_ext_startup() {
println('[ext] module startup')
}
@[export: 'vphp_ext_request_startup']
fn vphp_ext_request_startup() {
unsafe {
ext_request_boots++
}
}
@[php_function]
fn v_request_boot_count() int {
unsafe {
return ext_request_boots
}
}
这个例子里:
-
vphp_ext_startup()在 module init 时执行一次 -
vphp_ext_request_startup()在每次 request init 时执行一次 - 自动生成逻辑仍然会走
vphp_ext_auto_*,不会占用开发者自定义 hook 名字
更细文档:
3. Compiler / Export Pipeline
vphp
- parser
- repr
- builder
- emitter
- export
入口说明:
Documentation Map
如果你更希望按主题读,而不是按仓库目录读,可以直接走这张图:
- 产品总览:
- interop:
- 生命周期:
- OOP 导出:
- 值转换:
- 设计对比:
- 编译链:
Current Product Role
在整个
PHP + Vlang
vphp
- 语言桥接层
- Zend 导出层
- 上层
vslim/ vhttpd的基础设施层
也就是说:
-
vphp不直接定义应用模型 -
vphp也不直接定义 runtime - 它负责让上层框架和运行时具备“V 驱动 PHP”的能力
Current Highlights
从当前代码状态看,比较关键的能力有:
- 基于
ZVal的统一 interop 入口 - request-owned / persistent-owned / borrowed 所有权模型
- V 导出 PHP class / trait / interface / enum
- PHP 8 class attribute 导出
- V 导出对象恢复成 typed object pointer
Returning V closures to PHP
vphp provides a single, minimal ergonomic API for returning V closures to PHP. The recommended pattern is to use "universal" ZVal-based closures (arity 0..4) and the helper wrappers exposed on the Context.
Examples:
- Generic, typed wrapper (preferred when you already have a function type):
// If you have a typed function type, you can use the generic wrapper.
// The wrapper inspects arity at compile time and registers the correct bridge.
pub fn (ctx vphp.Context) get_cb() {
// Suppose my_cb is fn (vphp.ZVal, vphp.ZVal) vphp.ZVal
ctx.wrap_closure(my_cb)
}
- Convenience helpers (recommended for most users):
// Plain functions taking/returning ZVal can be wrapped easily:
pub fn my_cb(a vphp.ZVal, b vphp.ZVal) vphp.ZVal {
return vphp.ZVal.new_string(a.to_string() + "+" + b.to_string())
}
pub fn (ctx vphp.Context) get_cb2() {
// Prefer the single minimal API: either use the generic wrapper or the
// explicit ClosureUniversal alias with wrap_closure_universal. For example:
ctx.wrap_closure(my_cb)
}
Notes:
- Universal closures use ZVal for parameter and return types to avoid brittle comptime type reflection and to keep the bridge stable across V versions.
- Supported arity: 0..4. For unsupported arity, the wrapper will return null at runtime.
- The single generic entrypoint is
wrap_closure[T]; helper wrap_closure_from_fnNfunctions are provided for ergonomics.
Recommended Reading Order
如果你第一次看
vphp
- 先看这页
- 再看 docs/OVERVIEW.md
- 再看 docs/interop.md
- 再看 docs/oop_features.md
- 最后看 compiler/README.md