diff --git a/examples/project/ext.cc b/examples/project/ext.cc index 76e0f990..71df61d0 100644 --- a/examples/project/ext.cc +++ b/examples/project/ext.cc @@ -1,4 +1,5 @@ #include +#include #include "phpx_func.h" using namespace php; @@ -9,3 +10,15 @@ Int php_fn_test(Int a, Int b) { var_dump(php_uname()); return c; } + +static php::Str prop_base {ZEND_STRL("base"), true}; + +void php_foo____construct(php::Object& this_, php::Int value) { + std::cout << "hashCode: " << prop_base.str()->h << "\n"; + this_.setProperty(prop_base, value); +} + +php::Int php_foo__bar(php::Object &this_, php::Int a, php::Int b) { + std::cout << "hashCode: " << prop_base.str()->h << "\n"; + return this_.getProperty(prop_base).toInt() + a + b; +} \ No newline at end of file diff --git a/examples/project/ext.stub.php b/examples/project/ext.stub.php index bc4e03a1..54d1f996 100644 --- a/examples/project/ext.stub.php +++ b/examples/project/ext.stub.php @@ -1,4 +1,14 @@ bar(123, 342)); } \ No newline at end of file diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 4f5ec4dd..75c5ed4d 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -804,8 +804,12 @@ class CompilerBase extends \PhpAot\Core\Translator protected function parseFunctionDecl(Node\Stmt\Function_|Node\Stmt\ClassMethod $v): FunctionDef { // .stub 存根定义 C++ Native 函数,必须设置返回值类型 - if (!$v->returnType && $this->stubFile) { - $this->fatalError($v, 'The return type of the function `' . $v->name . '` must be specified'); + if ($this->stubFile and !$v->returnType) { + // 以下魔术方法都不能声明返回值类型 __construct()/__destruct()/__clone() + if (($this->method and !in_array($this->method, ['__construct', '__destruct', '__clone'])) or !$this->method) { + $name = $this->class ? $this->class . '::' . $v->name : $v->name; + $this->fatalError($v, 'The return type of the function `' . $name . '` must be specified'); + } } // 返回值不能是引用类型 if ($v->byRef) { @@ -814,7 +818,7 @@ class CompilerBase extends \PhpAot\Core\Translator $fnName = $this->parseIdentifier($v->name); $returnType = $this->parseTypeDecl($v->returnType, self::DECL_TYPE_OF_RETURN); - $functionDef = new FunctionDef($fnName, $returnType, $this->namespace); + $functionDef = new FunctionDef($fnName, $returnType, $this->namespace, $this->stubFile); $this->functionDef = $functionDef; $this->parseParams($v->params, $functionDef); @@ -828,10 +832,10 @@ class CompilerBase extends \PhpAot\Core\Translator if ($returnType !== self::TYPE_VOID) { $this->fatalError($v, 'main function must return void'); } - if ($this->checkArgType($functionDef->argInfoList[0]->type, self::TYPE_INT)) { + if (!$this->checkArgType($functionDef->argInfoList[0]->type, self::TYPE_INT)) { $this->fatalError($v, 'The first parameter of the main function must be of type `int`.'); } - if ($this->checkArgType($functionDef->argInfoList[1]->type, self::TYPE_ARRAY)) { + if (!$this->checkArgType($functionDef->argInfoList[1]->type, self::TYPE_ARRAY)) { $this->fatalError($v, 'The second parameter of the main function must be of type `array`.'); } } @@ -861,7 +865,6 @@ class CompilerBase extends \PhpAot\Core\Translator // 类方法不要保存到 functions 中 if ($this->class) { - $this->addArgument('this_', self::TYPE_OBJECT); if ($this->methodDef) { $this->functionDef->method = true; $this->methodDef->functionDef = $this->functionDef; @@ -870,6 +873,15 @@ class CompilerBase extends \PhpAot\Core\Translator $this->functionDefineInFile[$name] = $this->functionDef; } + // stub 函数,没有函数的具体实现,只有声明,实现在 C++ 或者 .so 中定义 + if ($this->functionDef->stub) { + $this->resetFunction(); + return ''; + } + + if ($this->class) { + $this->addArgument('this_', self::TYPE_OBJECT); + } foreach ($this->functionDef->argInfoList as $argInfo) { $this->addArgument($argInfo->name, $argInfo->type); } diff --git a/src/Php/Entity/FunctionDef.php b/src/Php/Entity/FunctionDef.php index b596b61c..55f33d1e 100644 --- a/src/Php/Entity/FunctionDef.php +++ b/src/Php/Entity/FunctionDef.php @@ -21,15 +21,17 @@ class FunctionDef public array $argInfoList = []; public int $argCountRequired = 0; public string $params = ''; - public string $namespace = ''; + public string $namespace; public bool $method = false; + public bool $stub = false; public bool $completed = false; - public function __construct(string $name, string $returnType, string $namespace = '') + public function __construct(string $name, string $returnType, string $namespace, bool $stub) { - $this->name = $name; + $this->name = $name; $this->returnType = $returnType; - $this->namespace = $namespace; + $this->namespace = $namespace; + $this->stub = $stub; } public function getNamespacedName(): string diff --git a/src/Php/Preprocessor.php b/src/Php/Preprocessor.php index 3689c70a..27a3b38f 100644 --- a/src/Php/Preprocessor.php +++ b/src/Php/Preprocessor.php @@ -266,6 +266,7 @@ class Preprocessor extends CompilerBase protected function prepareMethod(Node\Stmt\ClassMethod $v, Node\Stmt\Class_|Node\Stmt\Trait_|Node\Stmt\Enum_ $class): void { + $this->method = $v->name; $abstract = $v->flags & Modifiers::ABSTRACT; if (!$abstract) { $this->prepareFunction($v) . PHP_EOL; @@ -276,7 +277,7 @@ class Preprocessor extends CompilerBase } $fullClassName = $this->getFullClassName(); - $fullMethodName = $fullClassName . '::' . $v->name; + $fullMethodName = $fullClassName . '::' . $this->method; $this->classMethodOverride[strtolower($fullMethodName)] = false; // 查找父类是否有同名方法,递归查找 $fullClassNameLower = strtolower($fullClassName);