From 9c51551567dd09bc0cee3cc7a19f10339ff45524 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 11 Feb 2026 19:54:39 +0800 Subject: [PATCH] =?UTF-8?q?refactor(php):=20=E9=87=8D=E6=9E=84=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E5=99=A8=E5=9F=BA=E7=A1=80=E7=B1=BB=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E7=B1=BB=E5=92=8C=E5=87=BD=E6=95=B0=E6=8C=87=E9=92=88=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 getClassEntryPtr 方法重命名为 getClassId 并修改返回值为整数ID - 将 getFuncPtr 方法重命名为 getFuncId 并修改返回值为整数ID - 添加新的 getMethodPtr 方法用于获取方法指针 - 重新实现 getClassEntryPtr 和 getFuncPtr 方法,基于新的ID获取方法 - 更新方法调用逻辑以使用新的方法指针机制 - 在C++模板中添加 php_get_method 函数实现 - 更新PHP AOT辅助头文件中的函数声明 - 优化Reflection类中的反射异常处理和参数类型引用 --- src/Php/CompilerBase.php | 41 ++++++++++++++++++++++++++++------- src/Php/Reflection.php | 20 +++++++++++------ src/cpp/php_aot_helper.h | 13 ++++++----- src/template/extension.cc.php | 8 +++++++ tests/aot/method-call.phpt | 10 +++++++++ 5 files changed, 71 insertions(+), 21 deletions(-) create mode 100644 tests/aot/method-call.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 7271af66..11507af0 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -649,7 +649,7 @@ class CompilerBase extends \PhpAot\Core\Translator return implode(self::NAMESPACE_SEPARATOR, array_reverse($names)); } - protected function getClassEntryPtr(string $className): string + protected function getClassId(string $className): int { if (isset($this->classMap[$className])) { $id = $this->classMap[$className]; @@ -657,11 +657,10 @@ class CompilerBase extends \PhpAot\Core\Translator $id = $this->classIndex++; $this->classMap[$className] = $id; } - - return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')'; + return $id; } - protected function getFuncPtr(string $funcName, bool $macro = true): string + protected function getFuncId($funcName): int { if (isset($this->funcMap[$funcName])) { $id = $this->funcMap[$funcName]; @@ -669,12 +668,31 @@ class CompilerBase extends \PhpAot\Core\Translator $id = $this->funcIndex++; $this->funcMap[$funcName] = $id; } + return $id; + } + + protected function getClassEntryPtr(string $className): string + { + $id = $this->getClassId($className); + return 'php_get_class(' . $id . ', ' . $this->getLiteralString($className) . ')'; + } + + protected function getFuncPtr(string $funcName, bool $macro = true): string + { + $id = $this->getFuncId($funcName); if ($macro) { return $id . ', ' . $this->getLiteralString($funcName); } return 'php_get_func(' . $id . ', ' . $this->getLiteralString($funcName) . ')'; } + protected function getMethodPtr(string $class, string $method): string + { + $funcId = $this->getFuncId($class . '::' . $method); + $classId = $this->getClassId($class); + return 'php_get_method(' . $funcId . ', ' . $this->getLiteralString($method) . ', ' . $classId . ', ' . $this->getLiteralString($class) . ')'; + } + protected function parseFunctionDeclaration(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef { // .stub 存根定义 C++ Native 函数,必须设置返回值类型 @@ -3122,20 +3140,27 @@ class CompilerBase extends \PhpAot\Core\Translator } else { $class = ''; } + $method = $this->identifierToStr($expr->name); $nativeFunc = $this->findNativeMethod($expr, $object, $method); if ($nativeFunc) { return $this->parseNativeMethodCall($object, $nativeFunc, $expr->args); } - if (empty($expr->args)) { - return $object . '.exec(' . $method . ')'; - } + if ($this->isNamedMethod($expr->name)) { $funcName = $this->parseIdentifier($expr->name); } else { $funcName = ''; } - return $object . '.exec(' . $method . ', ' . $this->parseCallArgs($expr->args, $funcName, $class) . ')'; + + if ($class and $funcName) { + $method = $this->getMethodPtr($class, $funcName); + } + + if (empty($expr->args)) { + return $object . '.exec(' . $method . ')'; + } + return $object . '.exec(' . $method . ', {' . $this->parseCallArgs($expr->args, $funcName, $class) . '})'; } protected function identifierToStr(NodeAbstract $node, bool $require = true): string diff --git a/src/Php/Reflection.php b/src/Php/Reflection.php index 9dc59717..9bf6e3f2 100644 --- a/src/Php/Reflection.php +++ b/src/Php/Reflection.php @@ -9,7 +9,10 @@ namespace PhpAot\Php; use ReflectionClass; +use ReflectionException; use ReflectionFunction; +use ReflectionParameter; +use ReflectionUnionType; class Reflection { @@ -21,7 +24,7 @@ class Reflection if (!isset(self::$functions[$fn])) { try { $ref = new ReflectionFunction($fn); - } catch (\ReflectionException $e) { + } catch (ReflectionException $e) { return null; } self::$functions[$fn] = $ref; @@ -35,7 +38,7 @@ class Reflection if (!isset(self::$classes[$className])) { try { $ref = new ReflectionClass($className); - } catch (\ReflectionException $e) { + } catch (ReflectionException $e) { return null; } self::$classes[$className] = $ref; @@ -54,14 +57,14 @@ class Reflection if (!$returnType) { return null; } - if ($returnType instanceof \ReflectionUnionType) { + if ($returnType instanceof ReflectionUnionType) { return null; } return $returnType->getName(); } - public static function getFunctionParameter(string $fn, int $index): ?\ReflectionParameter + public static function getFunctionParameter(string $fn, int $index): ?ReflectionParameter { $func = self::getFunction($fn); if (!$func) { @@ -75,16 +78,19 @@ class Reflection return $args[$index]; } - public static function getClassMethodParameter(string $className, string $fn, int $index): ?\ReflectionParameter + public static function getClassMethodParameter(string $className, string $fn, int $index): ?ReflectionParameter { $classRef = self::getClass($className); if (!$classRef) { return null; } - $method = $classRef->getMethod($fn); - if (!$method) { + + try { + $method = $classRef->getMethod($fn); + } catch (ReflectionException $e) { return null; } + $args = $method->getParameters(); if ($index >= count($args)) { return null; diff --git a/src/cpp/php_aot_helper.h b/src/cpp/php_aot_helper.h index b6d85648..db66361a 100644 --- a/src/cpp/php_aot_helper.h +++ b/src/cpp/php_aot_helper.h @@ -1,20 +1,21 @@ #include -extern zend_class_entry *php_get_class(int class_id, const php::String &class_name); -extern zend_function *php_get_func(int func_id, const php::String &func_name); +extern zend_class_entry *php_get_class(int class_id, const php::Str &class_name); +extern zend_function *php_get_func(int func_id, const php::Str &func_name); +extern zend_function *php_get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name); -static inline php::Variant CALL(int func_id, const php::String &func_name, const php::ArgList &args) { +static inline php::Variant CALL(int func_id, const php::Str &func_name, const php::ArgList &args) { return php::call(php_get_func(func_id, func_name), args); } -static inline php::Variant CALL(int func_id, const php::String &func_name) { +static inline php::Variant CALL(int func_id, const php::Str &func_name) { return php::call(php_get_func(func_id, func_name)); } -static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name, const php::ArgList &args) { +static inline php::Variant CALL_SILENT(int func_id, const php::Str &func_name, const php::ArgList &args) { return php::silentCall(php_get_func(func_id, func_name), args); } -static inline php::Variant CALL_SILENT(int func_id, const php::String &func_name) { +static inline php::Variant CALL_SILENT(int func_id, const php::Str &func_name) { return php::silentCall(php_get_func(func_id, func_name)); } diff --git a/src/template/extension.cc.php b/src/template/extension.cc.php index ada04348..a1065048 100644 --- a/src/template/extension.cc.php +++ b/src/template/extension.cc.php @@ -41,6 +41,14 @@ zend_function *php_get_func(int func_id, const php::String &func_name) { return [func_id]; } +zend_function *php_get_method(int func_id, const php::Str &method_name, int class_id, const php::Str &class_name) { + if (UNEXPECTED([func_id] == nullptr)) { + auto ce = php_get_class(class_id, class_name); + [func_id] = php::getMethod(ce, method_name); + } + return [func_id]; +} + // literal strings php::Str [] = { format('Y-m-d H:i:s'); +var_dump($rs); +?> +--EXPECT-- +string(19) "2000-01-01 00:00:00"