@@ -72,8 +72,8 @@ func repeat_this(s *C.zend_string, count int64, reverse bool) unsafe.Pointer {
7272
7373这里有两个重要的事情要注意:
7474
75- * 指令注释 ` //export_php:function ` 定义了 PHP 中的函数签名。这是生成器知道如何使用正确的参数和返回类型生成 PHP 函数的方式;
76- * 函数必须返回 ` unsafe.Pointer ` 。FrankenPHP 提供了一个 API 来帮助你在 C 和 Go 之间进行类型转换。
75+ - 指令注释 ` //export_php:function ` 定义了 PHP 中的函数签名。这是生成器知道如何使用正确的参数和返回类型生成 PHP 函数的方式;
76+ - 函数必须返回 ` unsafe.Pointer ` 。FrankenPHP 提供了一个 API 来帮助你在 C 和 Go 之间进行类型转换。
7777
7878虽然第一点不言自明,但第二点可能更难理解。让我们在下一节中深入了解类型转换。
7979
@@ -82,16 +82,17 @@ func repeat_this(s *C.zend_string, count int64, reverse bool) unsafe.Pointer {
8282虽然一些变量类型在 C/PHP 和 Go 之间具有相同的内存表示,但某些类型需要更多逻辑才能直接使用。这可能是编写扩展时最困难的部分,因为它需要了解 Zend 引擎的内部结构以及变量在 PHP 中的内部存储方式。此表总结了你需要知道的内容:
8383
8484| PHP 类型 | Go 类型 | 直接转换 | C 到 Go 助手 | Go 到 C 助手 | 类方法支持 |
85- | --------------------| ---------------------| ----------| ----------------------| ----------------------| ------------|
86- | ` int ` | ` int64 ` | ✅ | - | - | ✅ |
87- | ` ?int ` | ` *int64 ` | ✅ | - | - | ✅ |
88- | ` float ` | ` float64 ` | ✅ | - | - | ✅ |
89- | ` ?float ` | ` *float64 ` | ✅ | - | - | ✅ |
90- | ` bool ` | ` bool ` | ✅ | - | - | ✅ |
91- | ` ?bool ` | ` *bool ` | ✅ | - | - | ✅ |
92- | ` string ` /` ?string ` | ` *C.zend_string ` | ❌ | frankenphp.GoString() | frankenphp.PHPString() | ✅ |
93- | ` array ` | ` *frankenphp.Array ` | ❌ | frankenphp.GoArray() | frankenphp.PHPArray() | ✅ |
94- | ` object ` | ` struct ` | ❌ | _ 尚未实现_ | _ 尚未实现_ | ❌ |
85+ | ------------------ | ------------------- | -------- | --------------------- | ---------------------- | ---------- |
86+ | ` int ` | ` int64 ` | ✅ | - | - | ✅ |
87+ | ` ?int ` | ` *int64 ` | ✅ | - | - | ✅ |
88+ | ` float ` | ` float64 ` | ✅ | - | - | ✅ |
89+ | ` ?float ` | ` *float64 ` | ✅ | - | - | ✅ |
90+ | ` bool ` | ` bool ` | ✅ | - | - | ✅ |
91+ | ` ?bool ` | ` *bool ` | ✅ | - | - | ✅ |
92+ | ` string ` /` ?string ` | ` *C.zend_string ` | ❌ | frankenphp.GoString() | frankenphp.PHPString() | ✅ |
93+ | ` array ` | ` *frankenphp.Array ` | ❌ | frankenphp.GoArray() | frankenphp.PHPArray() | ✅ |
94+ | ` mixed ` | ` any ` | ❌ | ` GoValue() ` | ` PHPValue() ` | ❌ |
95+ | ` object ` | ` struct ` | ❌ | _ 尚未实现_ | _ 尚未实现_ | ❌ |
9596
9697> [ !NOTE]
9798> 此表尚不详尽,将随着 FrankenPHP 类型 API 变得更加完整而完善。
@@ -111,16 +112,16 @@ FrankenPHP 通过 `frankenphp.Array` 类型为 PHP 数组提供原生支持。
111112func process_data (arr *C .zval ) unsafe .Pointer {
112113 // 将 PHP 数组转换为 Go
113114 goArray := frankenphp.GoArray (unsafe.Pointer (arr))
114-
115+
115116 result := &frankenphp.Array {}
116-
117+
117118 result.SetInt (0 , " first" )
118119 result.SetInt (1 , " second" )
119120 result.Append (" third" ) // 自动分配下一个整数键
120-
121+
121122 result.SetString (" name" , " John" )
122123 result.SetString (" age" , int64 (30 ))
123-
124+
124125 for i := uint32 (0 ); i < goArray.Len (); i++ {
125126 key , value := goArray.At (i)
126127 if key.Type == frankenphp.PHPStringKey {
@@ -129,28 +130,28 @@ func process_data(arr *C.zval) unsafe.Pointer {
129130 result.SetInt (key.Int +100 , value)
130131 }
131132 }
132-
133+
133134 // 转换回 PHP 数组
134135 return frankenphp.PHPArray (result)
135136}
136137```
137138
138139** ` frankenphp.Array ` 的关键特性:**
139140
140- * ** 有序键值对** - 像 PHP 数组一样维护插入顺序
141- * ** 混合键类型** - 在同一数组中支持整数和字符串键
142- * ** 类型安全** - ` PHPKey ` 类型确保正确的键处理
143- * ** 自动列表检测** - 转换为 PHP 时,自动检测数组应该是打包列表还是哈希映射
144- * ** 不支持对象** - 目前,只有标量类型和数组可以用作值。提供对象将导致 PHP 数组中的 ` null ` 值。
141+ - ** 有序键值对** - 像 PHP 数组一样维护插入顺序
142+ - ** 混合键类型** - 在同一数组中支持整数和字符串键
143+ - ** 类型安全** - ` PHPKey ` 类型确保正确的键处理
144+ - ** 自动列表检测** - 转换为 PHP 时,自动检测数组应该是打包列表还是哈希映射
145+ - ** 不支持对象** - 目前,只有标量类型和数组可以用作值。提供对象将导致 PHP 数组中的 ` null ` 值。
145146
146147** 可用方法:**
147148
148- * ` SetInt(key int64, value interface{}) ` - 使用整数键设置值
149- * ` SetString(key string, value interface{}) ` - 使用字符串键设置值
150- * ` Append(value interface{}) ` - 使用下一个可用整数键添加值
151- * ` Len() uint32 ` - 获取元素数量
152- * ` At(index uint32) (PHPKey, interface{}) ` - 获取索引处的键值对
153- * ` frankenphp.PHPArray(arr *frankenphp.Array) unsafe.Pointer ` - 转换为 PHP 数组
149+ - ` SetInt(key int64, value interface{}) ` - 使用整数键设置值
150+ - ` SetString(key string, value interface{}) ` - 使用字符串键设置值
151+ - ` Append(value interface{}) ` - 使用下一个可用整数键添加值
152+ - ` Len() uint32 ` - 获取元素数量
153+ - ` At(index uint32) (PHPKey, interface{}) ` - 获取索引处的键值对
154+ - ` frankenphp.PHPArray(arr *frankenphp.Array) unsafe.Pointer ` - 转换为 PHP 数组
154155
155156### 声明原生 PHP 类
156157
@@ -168,11 +169,11 @@ type UserStruct struct {
168169
169170** 不透明类** 是内部结构(属性)对 PHP 代码隐藏的类。这意味着:
170171
171- * ** 无直接属性访问** :你不能直接从 PHP 读取或写入属性(` $user->name ` 不起作用)
172- * ** 仅方法接口** - 所有交互必须通过你定义的方法进行
173- * ** 更好的封装** - 内部数据结构完全由 Go 代码控制
174- * ** 类型安全** - 没有 PHP 代码使用错误类型破坏内部状态的风险
175- * ** 更清晰的 API** - 强制设计适当的公共接口
172+ - ** 无直接属性访问** :你不能直接从 PHP 读取或写入属性(` $user->name ` 不起作用)
173+ - ** 仅方法接口** - 所有交互必须通过你定义的方法进行
174+ - ** 更好的封装** - 内部数据结构完全由 Go 代码控制
175+ - ** 类型安全** - 没有 PHP 代码使用错误类型破坏内部状态的风险
176+ - ** 更清晰的 API** - 强制设计适当的公共接口
176177
177178这种方法提供了更好的封装,并防止 PHP 代码意外破坏 Go 对象的内部状态。与对象的所有交互都必须通过你明确定义的方法进行。
178179
@@ -219,12 +220,12 @@ func (us *UserStruct) UpdateInfo(name *C.zend_string, age *int64, active *bool)
219220 if name != nil {
220221 us.Name = frankenphp.GoString (unsafe.Pointer (name))
221222 }
222-
223+
223224 // 检查是否提供了 age(不为 null)
224225 if age != nil {
225226 us.Age = int (*age)
226227 }
227-
228+
228229 // 检查是否提供了 active(不为 null)
229230 if active != nil {
230231 us.Active = *active
@@ -234,10 +235,10 @@ func (us *UserStruct) UpdateInfo(name *C.zend_string, age *int64, active *bool)
234235
235236** 关于可空参数的要点:**
236237
237- * ** 可空原始类型** (` ?int ` 、` ?float ` 、` ?bool ` )在 Go 中变成指针(` *int64 ` 、` *float64 ` 、` *bool ` )
238- * ** 可空字符串** (` ?string ` )仍然是 ` *C.zend_string ` ,但可以是 ` nil `
239- * ** 在解引用指针值之前检查 ` nil ` **
240- * ** PHP ` null ` 变成 Go ` nil ` ** - 当 PHP 传递 ` null ` 时,你的 Go 函数接收 ` nil ` 指针
238+ - ** 可空原始类型** (` ?int ` 、` ?float ` 、` ?bool ` )在 Go 中变成指针(` *int64 ` 、` *float64 ` 、` *bool ` )
239+ - ** 可空字符串** (` ?string ` )仍然是 ` *C.zend_string ` ,但可以是 ` nil `
240+ - ** 在解引用指针值之前检查 ` nil ` **
241+ - ** PHP ` null ` 变成 Go ` nil ` ** - 当 PHP 传递 ` null ` 时,你的 Go 函数接收 ` nil ` 指针
241242
242243> [ !WARNING]
243244> 目前,类方法有以下限制。** 不支持对象** 作为参数类型或返回类型。** 完全支持数组** 作为参数和返回类型。支持的类型:` string ` 、` int ` 、` float ` 、` bool ` 、` array ` 和 ` void ` (用于返回类型)。** 完全支持可空参数类型** ,适用于所有标量类型(` ?string ` 、` ?int ` 、` ?float ` 、` ?bool ` )。
@@ -356,7 +357,7 @@ func repeat_this(s *C.zend_string, count int64, mode int) unsafe.Pointer {
356357 str := frankenphp.GoString (unsafe.Pointer (s))
357358
358359 result := strings.Repeat (str, int (count))
359- if mode == STR_REVERSE {
360+ if mode == STR_REVERSE {
360361 // 反转字符串
361362 }
362363
@@ -375,14 +376,14 @@ type StringProcessorStruct struct {
375376// export_php:method StringProcessor::process(string $input, int $mode): string
376377func (sp *StringProcessorStruct ) Process (input *C .zend_string , mode int64 ) unsafe .Pointer {
377378 str := frankenphp.GoString (unsafe.Pointer (input))
378-
379+
379380 switch mode {
380381 case MODE_LOWERCASE:
381382 str = strings.ToLower (str)
382383 case MODE_UPPERCASE:
383384 str = strings.ToUpper (str)
384385 }
385-
386+
386387 return frankenphp.PHPString (str, false )
387388}
388389```
@@ -437,17 +438,17 @@ echo My\Extension\STATUS_ACTIVE; // 1
437438
438439#### 重要说明
439440
440- * 每个文件只允许** 一个** 命名空间指令。如果找到多个命名空间指令,生成器将返回错误。
441- * 命名空间适用于文件中的** 所有** 导出符号:函数、类、方法和常量。
442- * 命名空间名称遵循 PHP 命名空间约定,使用反斜杠(` \ ` )作为分隔符。
443- * 如果没有声明命名空间,符号将照常导出到全局命名空间。
441+ - 每个文件只允许** 一个** 命名空间指令。如果找到多个命名空间指令,生成器将返回错误。
442+ - 命名空间适用于文件中的** 所有** 导出符号:函数、类、方法和常量。
443+ - 命名空间名称遵循 PHP 命名空间约定,使用反斜杠(` \ ` )作为分隔符。
444+ - 如果没有声明命名空间,符号将照常导出到全局命名空间。
444445
445446### 生成扩展
446447
447448这就是魔法发生的地方,现在可以生成你的扩展。你可以使用以下命令运行生成器:
448449
449450``` console
450- GEN_STUB_SCRIPT=php-src/build/gen_stub.php frankenphp extension-init my_extension.go
451+ GEN_STUB_SCRIPT=php-src/build/gen_stub.php frankenphp extension-init my_extension.go
451452```
452453
453454> [ !NOTE]
@@ -567,9 +568,9 @@ extern zend_module_entry ext_module_entry;
567568
568569接下来,创建一个名为 ` extension.c ` 的文件,该文件将执行以下步骤:
569570
570- * 包含 PHP 头文件;
571- * 声明我们的新原生 PHP 函数 ` go_print() ` ;
572- * 声明扩展元数据。
571+ - 包含 PHP 头文件;
572+ - 声明我们的新原生 PHP 函数 ` go_print() ` ;
573+ - 声明扩展元数据。
573574
574575让我们首先包含所需的头文件:
575576
@@ -701,9 +702,9 @@ import "strings"
701702//export go_upper
702703func go_upper(s *C.zend_string) *C.zend_string {
703704 str := frankenphp.GoString(unsafe.Pointer(s))
704-
705+
705706 upper := strings.ToUpper(str)
706-
707+
707708 return (*C.zend_string)(frankenphp.PHPString(upper, false))
708709}
709710```
0 commit comments