diff --git a/examples/python/sys.php b/examples/python/sys.php new file mode 100644 index 00000000..0858cb00 --- /dev/null +++ b/examples/python/sys.php @@ -0,0 +1,24 @@ +get("PATH")); +} + + + +use numpy as np; + +function np() +{ + var_dump(np::$module); + var_dump(np::version->full_version); +} + + diff --git a/examples/vargs.php b/examples/vargs.php new file mode 100644 index 00000000..d0a744fe --- /dev/null +++ b/examples/vargs.php @@ -0,0 +1,10 @@ +argCountRequired = count($params); - foreach ($params as $param) { + $last = array_key_last($params); + foreach ($params as $i => $param) { // .stub 存根定义 C++ Native 函数,必须设置函数的参数类型 if ($this->stubFile and !$param->type) { throw new \RuntimeException('No type for ' . $this->parseIdentifier($param->var)); @@ -875,12 +876,20 @@ class CompilerBase extends \PhpAot\Core\Translator if ($param->byRef) { $this->fatalError($param, 'ByRef parameters are not supported'); } + if ($param->variadic and $i !== $last) { + $this->fatalError($param, 'Variadic parameters must be the last parameter'); + } $name = $this->parseIdentifier($param->var); $type = $this->parseParameterType($param, $name); - $list[] = $type . ' ' . $name; + if ($param->variadic) { + $list[] = self::TYPE_ARRAY . ' ' . $name; + } else { + $list[] = $type . ' ' . $name; + } $argInfo = new ArgInfo(); $argInfo->name = $name; $argInfo->type = $type; + $argInfo->variadic = $param->variadic; if (isset($param->default)) { $functionDef->argCountRequired = count($list) - 1; $argInfo->default = $this->parseIdentifier($param->default); @@ -1957,8 +1966,18 @@ class CompilerBase extends \PhpAot\Core\Translator if ($arg->name !== null) { $this->fatalError($arg, 'Named arguments are not supported'); } - $argInfo = $this->getArgInfo($arg, $nativeFunc, $i); - $list_args[] = $this->getTypeConvertedArg($arg, $argInfo); + $argInfo = $this->getArgInfo($arg, $nativeFunc, $i); + if ($argInfo->variadic) { + $vargs = array_slice($args, $i); + $list_vargs = []; + foreach ($vargs as $varg) { + $list_vargs[] = $this->getTypeConvertedArg($varg, $argInfo); + } + $list_args[] = '{' . implode(', ', $list_vargs) . '}'; + break; + } else { + $list_args[] = $this->getTypeConvertedArg($arg, $argInfo); + } } return implode(', ', $list_args); diff --git a/src/Php/Translator.php b/src/Php/Translator.php index 9ebba593..8480dce3 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -300,9 +300,13 @@ class Translator extends Preprocessor $argInfoList = $func->argInfoList; if ($argInfoList) { foreach ($argInfoList as $argInfo) { - $arg = $argInfo->type . ' ' . $argInfo->name; - if ($argInfo->default) { - $arg .= ' = ' . $argInfo->default; + if ($argInfo->variadic) { + $arg = self::TYPE_ARRAY . ' ' . $argInfo->name . '()'; + } else { + $arg = $argInfo->type . ' ' . $argInfo->name; + if ($argInfo->default) { + $arg .= ' = ' . $argInfo->default; + } } $list[] = $arg; } @@ -734,13 +738,23 @@ class Translator extends Preprocessor $cppCode = ''; $callParams = ''; foreach ($functionDef->argInfoList as $k => $argInfo) { - if ($argInfo->default) { - $argExpr = 'php::getCallArg(' . $k . ', ' . $argInfo->default . ')'; + $var = 'arg_' . $argInfo->name; + if ($argInfo->variadic) { + $cppCode .= $this->getIndent() . self::TYPE_ARRAY . ' ' . $var . ';' . PHP_EOL; + $cppCode .= $this->getIndent() . 'for (uint32_t i = ' . $k . '; i < php::getCallArgNum(); i++) {' . PHP_EOL; + $this->indentLevel++; + $cppCode .= $this->getIndent() . $var . '.append(php::getCallArg(i));' . PHP_EOL; + $this->indentLevel--; + $cppCode .= '}' . PHP_EOL; } else { - $argExpr = 'php::getCallArg(' . $k . ')'; + if ($argInfo->default) { + $argExpr = 'php::getCallArg(' . $k . ', ' . $argInfo->default . ')'; + } else { + $argExpr = 'php::getCallArg(' . $k . ')'; + } + $expr = $this->convertExprFromType($argInfo->type, $argExpr); + $cppCode .= $this->getIndent() . $argInfo->type . ' ' . $var . ' = ' . $expr . ';' . PHP_EOL; } - $expr = $this->convertExprFromType($argInfo->type, $argExpr); - $cppCode .= $this->getIndent() . $argInfo->type . ' arg_' . $argInfo->name . ' = ' . $expr . ';' . PHP_EOL; $callParams .= 'arg_' . $argInfo->name . ','; } diff --git a/tests/aot/variadic-args.phpt b/tests/aot/variadic-args.phpt new file mode 100644 index 00000000..8c2711fd --- /dev/null +++ b/tests/aot/variadic-args.phpt @@ -0,0 +1,26 @@ +--TEST-- +variadic args +--FILE-- + +--EXPECT-- +int(1) +int(2) +array(3) { + [0]=> + int(3) + [1]=> + int(4) + [2]=> + int(5) +} +