Hello, World!
本章节包含如何在非IDE的命令行环境下运行你的第一个 GS 程序、GS driver 的常用启动参数、GS driver shell 的常用方法等内容。面向初次运行 GS 程序、不了解GS driver 相关概念或操作的同学。阅读完本章节后,应当能够使用命令行运行 GS 程序、使用 shell 调用函数、操作数据、查询函数等。
注意:本教程假定你熟悉命令行操作。
1. driver 概念
driver 实际指代安装过程中我们安装的可执行文件,windows下为 gs.exe 其他系统下为 gs。它是 GS 语言的驱动程序,是用于编译运行 .gs 文件的解释器程序/在 driver 中我们可以动态的编译程序并执行,查看函数、宏、枚举的说明,查看当前内存占用信息,手动调用函数,调用分析工具等。
2. drvier 启动
查看安装过程中创建的/helloworld/src/helloworld.gs 项目目录下的 GS 源码,其代码如下所示:
public void main()
{
write("hello, welcome to g-bits!\n");
write("This is a language powered by g-bits!\n");
return;
}
main();
示例 2-1:gip init 初始化的默认 helloworld.gs 源码
我们用任意文本编辑器打开,并修改源码如下:
void main()
{
write("Hello,World!\n");
return;
}
main();
示例 2-2:一个打印 Hello,World!的程序
保存文件,并使用命令行打开至当前 helloworld 项目的的根目录 下,即\helloworld\路径下,运行如下命令编译并执行程序:
.\bin\gs.exe /r ./ /e ./src/helloworld.gs
此时可以看到终端窗口中字符串 Hello, world!被打印出来,同时来到了 driver 的 shell中,如下图所示:

好的,🎊恭喜你运行了属于你的第一个GS 程序。现在让我们暂时离开控制台窗口,了解下driver 常用的启动参数。
3.driver 常用启动参数
下面将介绍一些常用的启动参数,更详细的启动参数见drvier 启动参数。
/r设置根目录/e启动脚本/eq启动脚本,在脚本执行完成后不进入shell 而是退出/m可以带多个预加载的脚本,如果有多个用逗号隔开(,)--mount挂载目录/D预定义宏--require||--require all导入内置插件(用于兼容旧代码,详细说明见import章节中的相关说明)/c1开启命令行交互模式- --enable-jit [0,1,2] 启用 jit。0 代表解释执行,1 代表 asmjit,2代表 llvmjit。
其中/c1 常用于linux系统中,windows下是默认开启的。
此时再看我们之前的启动命令:
.\bin\gs.exe /r ./ /e ./src/helloworld.gs
实际 是将启动 driver 并将根目录设置在当前目录,并编译运行 helloworld.gs 启动脚本,接下来让我们简单尝试下,预加载脚本,挂载目录,预定义宏启动参数。
在helloworld/src/目录下让我们额外创建一个preload.gsh,内容如下:
write("load preload.gsh\n");
示例 3-1:预加载过程简单输出
调整helloworld/src/目录下 helloworld.gs 源码如下:
public void main()
{
write("Hello,World!\n");
write(lucky_num);
return;
}
main();
示例 3-3:添加宏展开代码的 helloworld.gs 源码
完成调整后目录结构如下:
helloworld
├─ vscode Vscode 配置文件
├─ src
| ├─preload.gsh 预加载脚本
| ├─helloworld.gs GS 源码
├─ .gitignore git 忽略配置文件
├─ package.json GIP 的包管理配置文件
├─ README.md 项目说明文档
同样在项目根目录helloworld/下以如下命令启动程序:
.\bin\gs.exe /r ./src/ /e ./helloworld.gs /m /preload.gsh --mount ./src::/source /D lucky_num=888
命令中我们以启动参数做了如下操作:
-
/r ./src/将helloworld/src/设为 driver 的根目录 -
/e ./helloworld.gs将 driver 启动脚本设为 helloworld.gs -
/m /preload.gsh预加载 preload.gsh 脚本 -
--mount ./src::/source将 /src 挂载为 /source 目录 -
/D lucky_num=888预定义宏,将 lucky_num 宏定义为数字 888 -
--require json导入 json 插件
运行的结果如下图:

可以看到源码中的
-
preload.gsh 预加载脚本
-
lucky_num:被正确宏展开为了数字888
此时不要关闭终端,让我们在 shell 中输入如下命令
'get_system_info()
检查输出map 表中的如下字段:
-
root_path: 可以看到/r启动参数设置的根路径 -
mount_info:可以看到我们将根路径挂载到了/source/路径下
接下来我们介绍下 driver shell的概念及常用的操作。
3. shell 介绍
3.1 shell 概念
Shell 是driver的一个命令行工具,它作为用户与 driver 之间的桥梁,负责接收用户输入的命令,解释并执行这些命令,同时将结果返回给用户。
Shell 本质是一个driver中持续运行的 GS 脚本,相应源码可查阅 shell.gs
当终端终端中带有如下形式输出时,说明shell以打开并可接收并执行命令。
Shell>
3.2 shell 常用方法
在 helloword 项目启动的 shell 中逐个尝试以下 shell 的常用方法并查看 shell 输出:
write("Hello,world!"),printf("Hello,world!")或'"Hello,world!"输出 "Hello,world!" 字符串- 在shell中可以使用
'单引号进行快捷打印
- 在shell中可以使用
man用于查找函数,枚举或宏说明- 想查看array相关的函数,在Shell敲入
man("array")或者敲man array, 两种写法是等价的。可以查找并看到array相关的函数描述,参数列表等。 - 想查看变量类型枚举信息,在Shell敲入
man ValueType
- 想查看array相关的函数,在Shell敲入
cls用于清空屏幕#define可以定义在shell 中使用的宏- 在shell分别敲入
#define new_num 666'new_num两条命令,查看 new_num 是否被正确的宏展开 - 出于安全考虑,覆盖同名的宏(无论是之前在shell中定义的还是环境中定义的),都会导致之后执行的代码发出警告
- 在shell分别敲入
find_object(handle|string name_or_id)查找一个object- 在shell敲入
'find_object(shell)可以查找到内置的 shell.gs 脚本的 object 实例 - 在shell敲入
find_object("/helloworld.gs").main()可以使用找到的 helloworld.gs 的 object 调用其公开的 main 函数
- 在shell敲入
get_obj_var(object ob, string var_name)查看某个object的私有变量- 在shell敲入
'get_obj_var(find_object(shell), "_shutdown_cmds")可以查找到内置的 shell.gs 脚本中 shutdown driver 的命令列表,为中英文 dot 符号构成的数组
- 在shell敲入
set_obj_var(object ob, string var_name, mixed val)设置某个私有变量的值,避免添加一个set函数->patch->删除这个set函数->patch这样的工作'set_obj_var(find_object(shell), "_shutdown_cmds", make_readonly(["down"]))设置内置的 shell.gs 脚本中 shutdown driver 的命令列表,现在键入down即可关闭driver
monkey.patch(program_name)或monkey.patch("代码文件路径")- 在不关闭shell的情况下修改 helloworld.gs 增加一个任意输出,敲入
monkey.patch("/helloworld.gs")再次敲入find_object("/helloworld.gs").main()可以看到修改被热更新到已有的 object 上 - 可以尝试通过
handle.get_all("program")查询当前有哪些program - 然后通过
monkey.patch(program_name)去热更新 update()也可以用于热更新, 但是实现原理 不太相同, update的逻辑更简单compile → destruct_object → load_static,但是对于有状态的对象,成员变量无法恢复,无法进行热更新。monkey.patch更为通用。
- 在不关闭shell的情况下修改 helloworld.gs 增加一个任意输出,敲入
=>用于切换 shell 执行时的域=> find_object("/helloworld.gs")即可进入 helloworld.gs 的 object 所在域,域的概念将在后续章节介绍=> ob.get_domain()可以切换到 ob 所属的域,之后shell的操作将在该域中执行=> nil可以切换到 shell 的默认域- 切换到目标域后的 shell 并不会持续占有域锁,而是仅当执行 shell 命令时占有域锁,执行完毕后会自动释放域锁。
- 特别注意,如果被切换的目标域始终不让出,可能导致 shell 无法进入而阻塞
clear env可以清除此前在shell中定义的变量、函数和宏child_objects(string | object name)某个对象的所有实例。||.用于退出driver