Project1

标题: 子进程与pipeline [打印本页]

作者: guoxiaomi    时间: 2019-4-5 19:54
标题: 子进程与pipeline
本帖最后由 guoxiaomi 于 2019-4-6 01:15 编辑

RPG Maker XP/VX/VA 可以使用 win32api 增强功能,但是更好的方法应该是创建一个独立的子进程,把复杂、费时的操作交给子进程来完成,游戏通过 pipeline 与子进程进行通讯。

当然我是不会了,于是找了大神帮忙写API的调用,封装和通讯协议由我完成。

在考虑到管道阻塞的情况下,使用了以下特殊的通讯协议:
1. 每次先向管道发送 4 个字节,表示接下来要发送的内容长度,接下来再发送实际的内容
2. 如果上一步的长度是 0,表示心跳帧(ping-pong)
3. 主进程在读取 pipe 中内容的之前,需要发送 ping 帧
4. 子进程接受到 ping 帧后必须立刻发送 pong 帧
5. 子进程在长时间未接受到 ping 帧的情况下自动结束

范例: 20190405-pipeline-reverse.zip (6.08 MB, 下载次数: 107)
范例里调用了 Scripts 文件夹下的 test.exe,这个 exe 实际上是使用 auto_python_to_exe 打包了同一目录下 test.py 生成的 exe 文件。
在 test.py 里写好了子进程的通讯协议和超时退出等行为。
注:
1. 由于RM中的Thread不是非常的稳定,所以这里不采用多线程的写法,需要定期调用 update 方法
2. 可以创建任意多个子进程,也可以主动结束子进程
3. 缓冲区的长度是 10kB,脚本里搜索 10240 即可找到

使用方法:
创建一个子进程对象,传入的参数是执行的命令行程序,代码块里是收到子程序发送的信息后回调的内容。
此处,如果安装了python,可以传入 "python Scripts/test.py"
RUBY 代码复制
  1. $pipeline = Pipeline.new("Scripts/test") { |msg|
  2.   p "recv msg: #{msg}"
  3. }

每帧更新,当收到信息后会执行上面的回调:
RUBY 代码复制
  1. $pipeline.update

向子进程发送消息,在范例里子进程接收到消息后会立刻返回消息.reverse:
RUBY 代码复制
  1. $pipeline.write("hello, world")

立即结束子进程:
RUBY 代码复制
  1. $pipeline.close


最主要的用途就是无限制的给RM提供功能,并且由于是独立进程不拖累RM自身的运行(甚至可以吃满CPU)

推荐使用Python+auto_python_to_exe,以及RubyMarshal库创建ruby的序列化对象。

当然你喜欢的话用Ruby、C、Lua、Javascript也都是可以的……

最后感谢 SixRC 写的后台运行脚本~

如果只是想后台跑一个程序,而不使用管道通讯,直接调用 CreateProcess 即可。
参见 create 方法内部,注意原先传入的参数 in_r, out_w 直接改成 0.
作者: SixRC    时间: 2019-4-5 21:11
本帖最后由 SixRC 于 2019-4-5 22:01 编辑


别打坛游了
快去修bug!
(不是很熟python(几乎不写) 整个逻辑稍微稍微懂)
(所以为什么要加一句buf[::-1])
(这样不是输出反了吗..?????)
删掉就正常了

作者: 正太君    时间: 2019-4-6 23:31
自从得知RM的进程是假的之后就对这个问题死心了...直到这篇文章出现,死去的心又重新跳动起来...

作者: 不死鸟之翼    时间: 2019-4-15 15:03
说起来我最近写了一个开源的RPC模块…
两边还可以在不同的电脑上
作者: guoxiaomi    时间: 2019-4-24 11:14
本帖最后由 guoxiaomi 于 2019-4-24 11:27 编辑

关于打包exe的问题,最近尝试使用auto_py_to_exe打包一个简单的websocket客户端程序,打包完毕有230M,看上去把Anaconda的半壁江山都打进去了,遂放弃。

最终选定的方案是 ruby + ocra + boxedapppacker,操作流程如下:

1. 安装ruby、ocra和boxedapppacker
首先我电脑上的ruby是32位的2.6.3:rubyinstaller-devkit-2.6.3-1-x86,安装后继续运行更新devkits,依次选1,2,3
  1. ridk install
复制代码

然后安装ocra-1.3.10:
  1. gem install ocra
复制代码

最后安装boxedapppacker:https://www.downloadfullsoft.com/fa/post/30628/

2. ocra打包程序
写好你的ruby代码,比如是 main.rb,直接用 ocra 打包:
  1. ocra main.rb --debug-extract
复制代码
注意 ocra 会试图运行一遍你的程序,你的程序一定要有退出的机制,否则后续的打包步骤不会执行。比如在加载库完毕后直接检测 ARGV,没有参数就立刻退出。
直接执行生成的 main.exe,由于打包时携带了参数--debug-extract,会在本地看到一个文件夹 ocraXXX.tmp,里面就是被 ocra 检测到的文件。
ocra会把文件解压到临时文件夹再执行,使用boxedapp打包会将文件夹解压到内存里,并且可以访问exe同级目录下的内容。

3. boxedapp打包
运行boxedapp:
1. 选择Files,用import directory载入ocra生成的bin,lib,src文件夹。你的main.rb应该在src内。当然你也可以添加更多的文件。
2. 选择 Registry,取消 enable
3. 选择options,勾选 Shared virtual environment with child process 和 Compress files
4. Icon、Version随意设置,splash screen是程序打开时候出现的宣传图,后台程序不需要这个。
5. 回到上面,选择Input.exe为 <ExeDir>\bin\ruby.exe,packed.exe选择合适的位置导出
6. Override command line:
  1. <ExeDir>\bin\ruby.exe <ExeDir>\src\main.rb
复制代码

7. 勾选Run packed exe in virtual environment,否则可能打包失败。
8. 点击build,收菜,测试 main.exe 是否正常执行。要注意exe运行和ruby脚本正式开始执行中间约有3s的间隔。即使不执行脚本改为执行
  1. <ExeDir>\bin\ruby.exe -v
复制代码
也有明显1s的延迟。

4. 推荐一个网站:https://repl.it/languages,可以在此网站上运行 sinatra 服务端用作测试。

因为记忆力越来越差了,就写在这里以后还能回来找找。实际上有些步骤并不是很确定非做不可,但是照着做应该没问题。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1