目录
之前一直看到php文档中有一个做GUI扩展,虽然这不是php擅长的,印象中这就不是它应该做的。同时文档很少,有点难看懂。今天记录下初次运行。
安装
测试环境 W in
php 版本如下
$ php71.exe -v
PHP 7.1.10 (cli) (built: Sep 26 2017 20:07:25) ( NTS MSVC14 (Visual C++ 2015) x86 )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
- 下载
ui 2.0.0 for Windows
下载对应版本DLL,根据我的php版本,我下载的是7.1-nts-x86,解压得到以下文件
- 复制php_ui.dll 到php的ext目录
- 复制 libui.dll 和 pthreadVC2.dll 到php目录
- php.ini 末尾添加以下配置以开启扩展
extension=php_ui.dll
- 运行php -m ,可以看到ui拓展已被加载
$ php71.exe -m
[PHP Modules]
bcmath
...
ui
...
[Zend Modules]
运行
扩展包里面还带了4个示例文件,分别是
snake.php
starfield.php
gallery.php
histogram.php
贪吃蛇 snake.php
php71.exe snake.php
该示例我是无法正常运行的,点击空格后,蛇只会移动一步,之后卡住。多次点击空格可以继续移动一个,鼠标滚轮一直滚动时也会一点点移动。
星空 starfield.php
该示例同贪吃蛇,一样会卡住。再连续滚动鼠标滑轮时,可以到20桢,停止时界面也随之停止。
组件库 gallery.php
该示例正常运行,包括界面二的进度条加载。体验还是挺丝滑的。
图标 histogram.php
该示例正常运行
卡住到可以运行
方法
snake.php
<?php
--- define (\"PHP_UI_SECOND\", 1000000);
+++ define (\"PHP_UI_SECOND\", 30);
define (\"PHP_UI_SNAKE_FPS\", 30);
starfield.php
--- $animator = new class(1000000/60, $stars) extends Executor {
+++ $animator = new class(1000000, $stars) extends Executor {
原因分析
以下为部分源码
if ($char == \" \") {
$this->pause = !$this->pause;
if ($this->pause) {
/* this allows the CPU to idle while paused */
$this->executor->setInterval(0);
} else {
/* this will (re)start the game */
$this->executor->setInterval(PHP_UI_SECOND/PHP_UI_SNAKE_FPS);
}
}
这里的 PHP_UI_SECOND/PHP_UI_SNAKE_FPS 应该设置每一帧刷新的时间,也就是控制帧率。但实际情况并没有按设想的运行。
以下时本机测试结果反向推测:
- setInterval 参数值应该是一个整数
- 这里单位可能是秒(按文档这里是微秒)
文档
UI\Executor::setInterval
public UI\Executor::setInterval(int $microseconds): bool
public UI\Executor::setInterval(int $seconds, int $microseconds): bool
按文档的写法,明细示例里面做(1000000/60)除法的赋值明显是不对的,我尝试改为整型。虽然可以运行,但是实际运行效果和预计的有很大出入。
有兴趣的可以移步ui/classes/executor.c查看
一些发现
测试代码
<?php
use UI\Window;
use UI\Size;
use UI\Controls\Box;
use UI\Executor;
$win = new class("TEST", new Size(640, 480), false) extends Window {
public function addExecutor(Executor $executor) {
$this->executors[] = $executor;
}
protected function onClosing() {
foreach ($this->executors as $executor) {
$executor->kill();
}
$this->destroy();
UI\quit();
}
protected function __destruct()
{
foreach ($this->executors as $executor) {
$executor->kill();
}
$this->destroy();
UI\quit();
}
};
$animator = new class() extends Executor {
protected function onExecute() {
echo 'onExecute:'.microtime(1).PHP_EOL;
}
public function __construct() {
parent::__construct(1000000);
}
};
$win->addExecutor($animator);
$win->show();
UI\run();
?>
修改间隔
以下3个写法是等价的,都是控制为1s
parent::__construct(1000000);
- 示例 1s
结果
onExecute:1636006041.6393
onExecute:1636006042.6396
onExecute:1636006043.6447
onExecute:1636006044.6519
符合预期
- 大于或等于1s时,比如2s
结果
onExecute:1636006200.6372
onExecute:1636006202.6475
onExecute:1636006204.649
符合预期
3. 小于1s时,比如 500000 微妙即0.5秒
结果
onExecute:1636006383.6496
onExecute:1636006383.6509
onExecute:1636006384.6474
onExecute:1636006384.6485
onExecute:1636006385.6446
执行间隔远小于设定值,但却是可以做到1秒内2次。一脸懵逼~~
4. 其他情况
这里就简单描述下情况,比较混乱
小于0.4秒间隔,输出3行后卡住。
小于0.6秒间隔,输出的奇怪行数量
总结
这毕竟是一个4年没有更新的项目了,没更新肯定有其原因,项目没有活力必然会有问题不能及时修复,现在就当了解和学习了。奇怪的执行间隔,确实是超出能力范围。我做了以下尝试:
- 尝试读懂源码并发现问题,没发现不对的地方。
- 一开始以为单位换算有无,去尝试重新编译dll,奈何win上编译坐实困难,并且再阅读原发时发现问题并不在这,作罢。
- 更换了不同php和php_ui版本进行测试,意外发现php_ui 2.0之前的版本并不会有这个问题,Execute正是是2.0引入的。
自己的猜想
- 某个地方可能有内置间隔,小于某个间隔后无法正常运行。
- 过短的间隔直接阻塞了
其他
- 本地安装了 php8-ts-64,测试下7.1-ts-64的dll包,并不能加载成功。
提示
Warning: PHP Startup: Unable to load dynamic library \'ui\'
- php7.0.12-nts-86,测试php_ui-2.0.0-7.0-nts-vc14-x86,一样卡住。
- 尝试在win上编译dll,下载的是vs2019,php版本7.3.33,都和建议版本有出入,果然行不通,不折腾了。
参考
PHP UI拓展介绍