跳到主要内容
版本:master

Program

1 概述

本章节将介绍 GS 语言的核心概念之一Program。我们将从 Program 的基本定义和它在整个对象模型中所扮演的角色讲起,详细阐述其创建方式,并通过具体示例展示如何在实际开发中查询、操作和使用 Program 。

本教程主要面向GS初学者,已经了解了 GS 基础语法,希望理解 GS 面向对象机制和运行时特性的同学。

通过阅读本章,您将能够理解 Program 的本质及其与 Object 的区别和联系、掌握动态创建和编译 Program 的方法、学会在运行时获取一个 Program 或 Object 的元信息(如组件、变量、函数列表)。使用Program 提供的方法进行类型检查、组件判断等高级操作。

2 program 基础

2.1 program 概念

在 GS 中,Program 是对象的蓝图或模板,它定义了某一类对象所共有的结构(包括变量、函数和组件等)。而通过 new_object或类似方法创建出来的,是一个个具体的 Object(实例)。

它们之间的关系,与 C++ 中 ClassClass 的实例对象 之间的关系非常相似。

  • Program 就像 C++ 中的 class。它本身不是对象,而是一个创建对象的模具。它在内存中通常只有一份。
  • Object 就像 C++ 中通过 new关键字创建出的对象实例。你可以根据同一个 Program 创建出无数个 Object。

简单来说:Program 是类型本身,Object 是该类型的值。

2.2 program 的创建

通常情况下 Program 通常通过编译 .gs源文件静态创建。当带有/e参数启动 driver 时,脚本import导入,component组件的所有脚本内容均被编译为单独的 program,在启动任意脚本后可以在shell 输入以下命令来查看已创建的program:

'program.get_all();

示例2-1:查看已创建的 program 实例

输出较长,此处不再给出。从示例获取的输出结果中可以看到除了自己编写的脚本外,输出中还有许多 GS 内置脚本的 program。

此外,GS 提供了 compile_program函数来实现运行时动态编译,GS 允许在运行时创建或更新 Program。compile_program外部函数的函数原型如下:

/**
* 动态编译一个 Program
* @param string file_name: 程序对应的文件名(例如 "game/MyObject.gs")
* @param mixed file_content: 【可选】文件的源代码内容。如果为 nil,系统会尝试从 file_name 路径读取文件。
* @param bool force_recompile: 【可选】是否强制重新编译,即使源文件未更改。
* @param bool compile_for_patch: 【可选】是否为打补编译,会影响编译策略。
* @param bool keep_old_program 【可选】重新编译后是否保留旧程序。
* @return bool: 返回编译Program 是否成功的bool标记。
*/
bool compile_program(string file_name, mixed file_content = nil, bool force_recompile = false, bool compile_for_patch = false)

​ 示例2-1:compile_program 函数原型

​ 动态编译是实现热更新猴子补丁(Monkey Patching) 的基石。若要了解更多 program 热更新相关内容请参照手册,链接:热更新手册

2.3 program 常用功能

2.3.1 获取对象的program

有两种主要方式获取一个对象的 Program:

// 方式一:通过已知的程序名称字符串查找,以gs内置的 base64.gs 脚本为例子
string object_name = "/gs/util/base64.gs";
program base64_program = program.find_by_name(object_name);
printlnf("Found program '%O' from name.", base64_program);

// 方式二:通过一个具体的对象实例获取其 Program
base64_program = nil;
object my_object = new_object("/gs/util/base64.gs"); // 某个已有的对象
base64_program = my_object.get_program();
printlnf("Got program '%O' from object.", base64_program);

示例2-2:获取program句柄

示例对应的输出如下:

Found program 'program[2887332:v0]/gs/util/base64.gs' from name.
Got program 'program[2887332:v0]/gs/util/base64.gs' from object.

2.3.2 查询 program 的构成信息

获取到 Program 后,可以查询其内部结构:

// 方式一:通过已知的程序名称字符串查找,以gs内置的 base64.gs 脚本为例子
string object_name = "/gs/util/base64.gs";
program base64_program = program.find_by_name(object_name);

// 获取这个 Program 定义的所有组件列表
array components = base64_program.get_components();
writeln(components);

// 获取这个 Program 定义的所有成员变量列表
array variables = base64_program.get_object_vars();
writeln(variables);

// 获取这个 Program 定义的所有成员函数列表
array functions = base64_program.get_functions();
writeln(functions);

示例2-3:获取program构成信息

对应的输出如下:

[ /* sizeof() == 1 */
program[2887332:v0]/gs/util/base64.gs,
]
[ /* sizeof() == 1 */
[ /* sizeof() == 3 */
"decodemap",
ValueType.BUFFER(11),
0,
],
]
[ /* sizeof() == 4 */
"::entry",
"remap",
"encode",
"decode",
]

3. 拓展阅读

更多 program 相关细节,外部函数(如获取依赖的program列表,获取所有依赖该program的object列表)、热更新等内容请参照 program 手册、 program 外部函数文档、热更新手册:

4. 总结

本章我们系统地梳理了 Program 的核心概念,明确了它作为对象模板的本质,以及与具体实例之间的区别。我们掌握了动态创建和编译 Program 的方法,这是实现热更新等高级功能的基础。通过示例,我们学会了如何在运行时查询 Program 的元信息。

理解 Program 是学习 GS 运行时系统的关键一步,接下来让我们学习由 Program 创建的实例 Object 的内容学习。