首页 >> 大全

rust + gnome.gtk 实现的【图形用户界面】版 [npm

2023-09-18 大全 28 作者:考证青年

-

工程入口:#-

这是一款加持了【图形用户界面】的npm - (名曰:问卷)。即,根据【问卷】配置文件,以人-机交互的形式,收集终端用户的【回答结果】。这里提到的【问卷配置】与【回答结果】都是*.json格式的字符串(或文件)。

【问卷】既能够作为.exe文件被双击运行,也支持作为.dll文件被链接和调用-间接运行。

在函数调用期间,会有gnome图形界面被弹出和提示用户输入问题答案。

制作这款工具的动机

我最近花了两个月的业余时间制作【问卷】这款工具的直接冲动来源于:将公司【前端-脚手架安装向导】从·命令行交互·升级为·图形界面互动·的构想。其路线图大约包括:

后来,我越做这款工具,越是觉得它的·通用性·还是比较高的。其使用场景不应仅只局限于【脚手架-安装过程】的现场配置收集。相反,任何含有【意见咨询】类功能的使用场景都可以考虑使用这款(或这类)工具。而,工具链的后续处理环节,再根据被收集的反馈结果,做定制化的“裁剪”。比如,“裁剪”脚手架内置的工程原型,使其更符合项目要求。

于是,我将这款工具从“脚手架-安装向导”更名为“问卷”。同时,它“下一步”再“下一步”的使用风格真心地相像于传统的应用软件的【安装向导】。【情怀】--- 在我认知体系中的任何软件安装都应该是“下一步”再“下一步”...最后“完成”;并且,其步骤越多,越有仪式感。

另一方面,在【rust桌面应用】方向投入更多业余精力也符合我个人对掌握rust技术栈的成长规划。即,

最后我的愿景是:在IoT嵌入式设备上“开花结果”。这对rust技术栈本身来说真不是问题。它已经一次又一次地证明其实力。愿景的实现主要还是看我对rust的掌握能够达到什么水平。

综上所述,实践rust的务实路径:wasm-> GUI App->IoT嵌入式编程。使用rust做一些GC类语言想做,而做不好的事。

即便作为是一名懒惰的程序员,我也得掌握两个计算机语言

前者中佼佼者䊨在:“铺得面广+无处不在”,解决“温饱”问题;后者中“剩者”的立足点是:“足够地快+内存安全”,解决“小康”问题。我要是能达到这个目标,那可真是:“中年危机远离我”。

技术

简单地讲,rust写业务逻辑 +gtk组件库画界面。

依赖说明

eval

log与

quick-xml

gdk-,gio,glib,gtk

毕竟,【问卷】功能单一,所以用到的第三方依赖项不多。此外,

开发环境搭建

不熟悉rust + gtk + win32技术栈的小伙伴儿请移步我的另一篇技术分享:为 Rust 原生 gui 编程,搭建 win32 开发环境。

工具链版本

鉴于之前使用rust + wasm完成【网络加密通讯】功能的踩坑经验,我这次显示地将绑定了适用的版本-2021-03-25--pc--gnu。若你的本地安装版本与之不匹配,请根据编译的报错信息, ***正确的 版本。就开发环境而言,对非用户不友好了,实在对不住。

工程打开方式

请从 ->【文件】->【打开工作区】->选择文件.\main.code-。然后,在【工作区】下有三个子工程

.
├─ rust-gui     # 这是`rust + gnome.gtk3`的原生图形界面开发子工程
├─ npmjs发布包  # 对应了 npm 包 https://www.npmjs.com/package/scaffold-wizard
└─ 简单功能演示  # node-ffi 封装的简单演示用例

_图形用户界面和命令行界面_图形用户界面gui

构建 cargo build或cargo build --

输出两个关键结果

-是cargo new --bin与cargo new --lib的混合体。

cargo test

执行针对的单元测试。还没有添加【集成测试】与【基准测试】。

cargo run node build.js或node build.js --

这里执行js程序有点突兀。但,它是被用来攒“绿色安装包”的。安装包的目录结构如下

.
├─ bin    # 若 windows 发行包,此目录需要包括 41 个 dll/exe 文件。若 Linux 发行包,仅 1 个 exe 文件。
|  ├─ ...
│  ├─ scaffold-wizard.exe # 仅出现在 target/setup-bin 目录下
|  ├─ ...
│  └─ scaffold_wizard.dll # 仅出现在 target/setup-lib 目录下
├─ lib    # 仅 windows 发行包需要此目录
│  └─ gdk-pixbuf-2.0
├─ share  # 仅 windows 发行包需要此目录
│  ├─ glib-2.0
│  └─ icons
├─ assets
│  ├─ prompt-manifest.json # 【问卷配置】样板文件
│  ├─ log4rs.json          # 日志配置文件
│  └─ images               # 自定义组件的图片
└─ logs   # 运行时滚动日志输出目录。

如上所述,要攒这么复杂的目录结构,使用编写构建程序绝对是省时省力的明智选择。

npm i -g archiver
node build.js

上面的命令执行之后,其会在目录下,创建两个子文件夹和两个zip文件

双击运行“绿色安装包”内的bin/-.exe。便可,在msys2包管理器环境之外,运行应用程序。同理,“绿色安装包”内的.dll也能够脱离msys2地被链接调用。但要稍稍再复杂一些。

build.rs

每当执行cargo指令时,这个构建程序也都会被执行。在目录下,它会创建若干指向msys2的符号链接。所以,强调:环境变量需要被配置,编译才能被正常地执行。

输入/输出说明 可执行文件的命令行参数

前端脚手架安装向导 1.0
张浩予 
以【问卷】的形式,收集开发者对前端工程原型的“裁剪”条件信息USAGE:scaffold-wizard.exe [OPTIONS]FLAGS:-h, --help       Prints help information-V, --version    Prints version informationOPTIONS:-i, --input-file    【问卷配置】 json 文件(包括:题面,选项,默认值)。缺省此参数会弹出【文件选择对话框】要求你临时选择一个 json 文件。-l, --log4rs-file     JSON 格式的 log4rs 配置文件。忽略此参数,程序会试从(1).exe 文件所在的同级目录(2)程序被执行的工作目录寻找 ../assets/log4rs.json 文件。若两处都没有配置文件,程序日志功将不会被开启。-o, --output-file  【问卷】的答案清单 json 文件。默认输出文件是 answers.json。并且,输出文件会被放置于与输入文件(--input-file)相同的目录里。

【问卷配置】json文件

它全方位地抄袭了 的 部分。但是,【回调函数钩子】那块,我是实在抄袭不来,原因包括:

所以,现在阶段,我暂停点开这个方向的“科技树”。

另一方面,作为对缺失【回调函数钩子】的补偿,我在如下几处添加了新配置属性:

给"type": "input"类型(即,文本输入框)添加了"": "port"子类。其专门收集【数字类型】,取值范围在1000 ~ 99999的端口号。样板配置如下:

{"appPort": { // 这个问题唯一标识字符串。相当于主键 ID。"when": "subprojects.app", // 条件表达式,当前问题是出现在交互流程中(true),还是被跳过(false)。"type": "input", // 文本输入框"subType": "port", // 端口数字输入框"message": "请输入 移动端 webpack dev server 监听端口号", // 题面"required": true, // 是否必填"default": 9010 // 默认值},
}

给"type": "list"类型(即,单选题)的每一个单选项添加了when(布尔)表达式。从而,根据上下文内容,动态地决定当前单选项是否被显示出来。样板配置如下:

{"compUiLib": { // 这个问题唯一标识字符串。相当于主键 ID。"when": "subprojects.component", // 条件表达式,当前问题是出现在交互流程中(true),还是被跳过(false)。"type": "list", // 单选题"message": "请选择 基于哪款【UI 组件库】做二次开发实现组件", // 题面 - 标题"choices": [{ // 题面 - 单选项1"name": "不使用UI组件库", // 【显示用】完整名"short": "无", // 【显示用】简称名 - 暂时尚未使用"value": "none" // 【程序引用】此选项的唯一标识字符串}, { // 题面 - 单选项2"when": "compWhichEnd == 'pcBrowser'", // 此选项是否出现的`when`表达式"name": "Element UI", // 【显示用】完整名"short": "Element", // 【显示用】简称名 - 暂时尚未使用"value": "elementUI" // 【程序引用】此选项的唯一标识字符串}, { // 题面 - 单选项3"when": "compWhichEnd == 'mobileBrowser'", // 此选项是否出现的`when`表达式"name": "Vant", // 【显示用】完整名"short": "vant", // 【显示用】简称名 - 暂时尚未使用"value": "vant" // 【程序引用】此选项的唯一标识字符串}]},
}

给"type": ""类型(即,多选题)的每一个多选项添加了mutex: 属性。"mutex": true表示该选项具有排它性。若其被选中,则该选项只能被单选。样板配置如下:

{"subprojects": { // 这个问题唯一标识字符串。相当于主键 ID。"type": "checkbox", // 多选题"message": "请选择 工程类型", // 题面 - 标题"required": true, // 是否必填"choices": [{ // 题面 - 多选项1"name": "PC浏览器-管理界面", // 【显示用】完整名"short": "中后台", // 【显示用】简称名 - 暂时尚未使用"value": "admin", // 【程序引用】此选项的唯一标识字符串。比如,subprojects.admin"checked": false // 初始选中状态}, { // 题面 - 多选项2"name": "本地 H5 插件", // 【显示用】完整名"short": "移动插件", // 【显示用】简称名 - 暂时尚未使用"value": "app", // 【程序引用】此选项的唯一标识字符串。比如,subprojects.app"checked": false // 初始选中状态}, { // 题面 - 多选项3"name": "组件/模块/微前端应用", // 【显示用】完整名"short": "组件/模块/微前端", // 【显示用】简称名 - 暂时尚未使用"value": "component", // 【程序引用】此选项的唯一标识字符串。比如,subprojects.component"checked": false, // 初始选中状态"mutex": true // 是否为单选}, { // 题面 - 多选项3"name": "RUST 语言 WEB 字节码 NPM 模块", // 【显示用】完整名"short": "RUST + WASM + NPM", // 【显示用】简称名 - 暂时尚未使用"value": "wasm", // 【程序引用】此选项的唯一标识字符串。比如,subprojects.wasm"checked": false, // 初始选中状态"mutex": true // 是否为单选}, { // 题面 - 多选项4"name": "RUST 语言原生 GUI 应用", // 【显示用】完整名"short": "RUST + GTK3 APP", // 【显示用】简称名 - 暂时尚未使用"value": "rust_gui", // 【程序引用】此选项的唯一标识字符串。比如,subprojects.rust_gui"checked": false, // 初始选中状态"mutex": true // 是否为单选}]},
}

【回答结果】json文件

首先,它会被输出至和输入文件相同的文件夹内。

其次,它全方位地抄袭了 的 部分。

最后,补充说明:

调用·动态链接库

注意:

同步接口调用

const fs = require('fs');
const ffi = require('ffi');
const ref = require('ref');
const path = require('path');
const util = require('util');
// 准备【问卷配置】`json`文件
const homeDir = path.resolve('target/setup-lib');
const questionsFile = path.join(homeDir, 'assets/prompt-manifest.json');
const readFile = util.promisify(fs.readFile);
readFile(questionsFile, {encoding: 'utf8'}).then(questions => {// 加载 DLLconst dllFile = path.join(homeDir, 'bin/scaffold_wizard.dll');const dllDir = path.dirname(dllFile);const scaffoldWizard = ffi.Library(dllFile, {inquire: ['string', ['string', 'string', 'string']],});// 调用 DLL// inquire(...) 一共有三个输入参数// (1) JSON 格式字符串,包括了【问卷配置】// (2) 被加载 DLL 文件所在的目录。以此,来寻找 assets\images 目录。// (3) log4rs 的配置文件路径。传一个空指针,表示关闭日志功能。// 输出返回值是 JSON 格式字符串,包括了【回答结果】const answers = scaffoldWizard.inquire(questions, dllDir, ref.NULL_POINTER);console.info('被收集的答案包括', answers);
});

异步接口调用

const fs = require('fs');
const ffi = require('ffi');
const ref = require('ref');
const path = require('path');
const util = require('util');
// 准备【问卷配置】`json`文件
const homeDir = path.resolve('target/setup-lib');
const questionsFile = path.join(homeDir, 'assets/prompt-manifest.json');
const readFile = util.promisify(fs.readFile);
readFile(questionsFile, {encoding: 'utf8'}).then(questions => {// 加载 DLLconst dllFile = path.join(homeDir, 'bin/scaffold_wizard.dll');const dllDir = path.dirname(dllFile);const scaffoldWizard = ffi.Library(dllFile, {inquireAsync: ['void', ['string', 'string', 'string', 'pointer']]});// 调用 DLL// inquire(...) 一共有三个输入参数// (1) JSON 格式字符串,包括了【问卷配置】// (2) 被加载 DLL 文件所在的目录。以此,来寻找 assets\images 目录。// (3) log4rs 的配置文件路径。传一个空指针,表示关闭日志功能。// 输出返回值是 JSON 格式字符串,包括了【回答结果】scaffoldWizard.inquireAsync(questions, dllDir, ref.NULL_POINTER, ffi.Callback('void', ['string', 'string'],finishedBuilder((err, answers) => {if (err) {console.error('失败原因', err);} else {console.info('被收集的答案包括', answers);}})));
});
function finishedBuilder(callback){let timerId;const holding = () => { // 锁住 event loop,不立即结束程序。timerId = setTimeout(holding, 1000 * 60 * 60);};holding();return (err, answers) => {clearTimeout(timerId); // 解锁return callback(err, answers);};
}

N-API封装

即将到来。

Neon封装

即将到来。

执行演示

运行这款工具分发包的最简单方式就是:

双击\setup-bin\bin\-.exe

直接弹出【文件选择对话框】,默认打开\setup-bin\文件夹,要求你选择一个【问卷配置】json文件。

选择-.json文件,点击【打开】按钮。

开始回答问题。

期间,不能退出。

完成所有问题之后,点击【完成】按钮。

程序退出。

【回答结果】json文件被输出到和输入文件相同的目录下,文件名为.json。

我已经在 10x64与 7x64亲自验证过了。

运行test case rust test case

从打开工程

菜单 -> 终端 -> 运行任务 ->test-sync

运行 test case

node调用的test case

推荐node版本是10

$ node npm-module/test.js

希望路过“大神”帮我看看

我这cargo build --编译出来的dll与exe都有点儿大(大约20MB)。这似乎有些不正常。路过的【神仙哥哥】与【神仙妹妹】是否可以帮我看看,我这是代码或编译配置,哪里有问题呀?

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了