一静态强类型语言的运行时类型扩展与反射方法与流程

文档序号:20077636发布日期:2020-03-10 09:55阅读:185来源:国知局
一静态强类型语言的运行时类型扩展与反射方法与流程

本发明涉及计算机编程技术领域,特别是涉及一静态强类型语言的运行时类型扩展与反射方法。



背景技术:

游戏应用程序是一类关注运行性能的应用程序。为了充分发挥硬件的特性和性能,游戏无论是在pc,移动还是主机平台,游戏应用程序始终以本地代码的形式运行,而不是运行在虚拟机上。因此,游戏和游戏引擎通常使用静态强类型语言开发核心模块,通过编译器的优化阶段和后端,最后映射到本地代码。

但是静态强类型的语言,例如c++编程语言,虽然有着高级编程语言的绝大部分特性,但是为了效率,在运行期都会做类型擦除(typeerase),从而坍塌成低级语言的执行代码。这就导致静态强类型语言在运行期会丢失几乎大部分的编译期的信息。例如c++编程语言,仅仅保留了部分rtti的信息以供运行期类型转换的功能。

游戏应用程序是由游戏引擎等工具链生成出的,并且游戏引擎属于超大规模复杂度的软件,需要多种语言,多种框架甚至多个中间件协同工作。编辑器往往要求其他语言同引擎的开发语言能够良好的交互,游戏玩法(gameplay)的开发要求游戏引擎的执行逻辑有良好的可扩展性,产出的游戏内容还需要正确的持久化,复杂逻辑的debug等诸多需求。而单薄的运行期明显无法肩负重任。因此我们为诸如此类的静态强类型语言设计了一个运行期的扩展方案,并在c++编程语言中给出了一个实现。



技术实现要素:

本发明的目的是提供一静态强类型语言的运行时类型扩展与反射方法,以解决上述问题。

为实现上述目的,本发明提供了一静态强类型语言的运行时类型扩展与反射方法,包括:通过静态强类型语言的编译期类型萃取,通过静态强类型的编译期元编程技术,获取类型的基本信息,类型的语义和语态分析;

通过将静态强类型语言的编译期类型擦除,利用编译期元编程将不同的编译期类型用一种统一的模型描述;

利用编译期元编程和函数式编程将普通的函数,成员函数,静态成员函数,仿函数及lambda表达式,用统一的模型来描述其函数的返回值及参数列表,并提供调用的接口。

进一步地,所述数据的动态类型标志符的种类表:分别为无类型0,布尔类型1,整数类型2,浮点数类型3,字符串类型4及用户自定义类型5。

进一步地,还包括数据模型联合结构体:当类型为布尔和整数时,存储实体为num_i的64位整数;当类型为浮点数时,存储实体为num_d的浮点数;当存储类型为字符串和object的时候,存储实体是一个可以被gc回收的对象指针,名为obj;而raw_p作为扩展保留使用。

进一步地,存储和管理任何主语言的类型对象的过程为:

201,联合结构体用来作为访问任何类型数据实体的访问指针;

202,获取数据的动态类型标志符;

203,判断数据类型是否为无类型;

204,判断数据类型是否为整数类型;

205,判断数据类型是否为浮点数类型;

206,判断类型是否为具有算数运算的数值类型;

207,判断数据类型是否为对象类型;

208,判断数据类型是否具有值语义;

209,把数据当做布尔类型获取值,不会抛出异常,只要数据不为nil或者非空的对象都为真,反之为假;

210,将数据作为整数类型取值,若数据类型不为整数类型的兼容类型会抛出异常;

211,将数据作为字符串类型取值,若数据类型无法转换为字符串,会抛出异常;

213,将数据作为c风格字符串取值,若数据类型不是字符串类型,会抛出异常;

213,将数据作为浮点数类型取值,若数据类型不为浮点类型的兼容类型会抛出异常;

214,泛型的数据获取接口,如果t是用户自定义类型,且数据类型与用户自定义不匹配,则抛出异常;

215,判断数据类型是否为用户自定义类型;

216,将数据对象设置为nil;

217,将数据对象设置为布尔值;

218,将数据对象设置为整数值;

219,将数据对象设置为浮点数值;

220,将数据对象设置为字符串;

221,将数据对象设置为用户自定义类型的对象;

222,泛型的设置数据对象的接口;

223,创建一个空的数据对象;

224,创建一个布尔类型的数据对象;

225,创建一个整数类型的数据对象;

226,创建一个浮点类型的数据对象;

227,创建一个字符串类型的数据对象;

228,创建一个用户自定义类型的数据对象;

229,泛型的创建数据对象的接口;

230,运行时通过元数据类型创建一个默认的数据对象实体;

231,运行时通过数据类型的字符串创建一个默认的数据对象实体。

进一步地,元数据和类型成员数据的元数据处理过程为:

301,类型元信息中这个类型的名称;

302,类型元信息中这个类型的id编号;

303,类型元信息中这个类型的所有的成员方法集合;

304,类型元信息中这个类型的所有成员变量(字段)的集合;

305,类型元信息中这个类型的构造方法;

306,类型元信息中该类型的父类类型,只支持单继承;

307,为类型元信息注册一个成员方法的接口;

308,为类型元信息注册一个成员变量的接口;

309,为类型元信息设置构造函数的接口;

310,为类型元信息设置基类类型的接口;

311,通过函数名称来获取类型元信息的成员函数元信息;

312,通过索引值来访问类型元信息成员函数元信息;

313,通过字段名称来访问字段的元信息;

314,通过索引值来访问类型元信息的字段元信息;

315,获取类型元信息的父类型元信息;

316,获取类型元信息的构造函数元信息;

317,获取类型元信息的类型名称,

318,抽象接口,用于设置成员字段的数据;

319,抽象接口,用于获取成员字段的数据;

320,字段元信息的字段名称;

321,字段元信息的所属类型名称;

322,该字段的类型元信息;

323,该字段是否是一个静态字段,而非实例字段;

324,该字段是否是只读的属性;

325,设置字段的只读属性值;

326,获取字段的只读属性值;

327,设置字段的静态属性值;

328,获取字段的静态属性值;

329,设置所属类型的类型名称;

330,获取所属类型的类型名称;

331,设置字段的名称;

332,获取字段的名称;

333,设置字段的类型元信息;

334,获取字段的类型元信息。

进一步地,函数形参类型和返回值类型的制作过程为:

401,调用一个对象成员函数的准备阶段,它传入一个对象的实例,并返回一个数据栈,数据栈用来压入函数调用的形参列表;

402,完成一个成员函数的调用,它从数据栈中读入数据并一次传递给类型擦除前的本地函数;

403,成员函数的名称;

404,成员函数所属类型的类型元信息;

405,成员函数的类型;

406,成员函数是否是静态方法;

407,成员函数的形参列表,列表的元素是参数元信息;

408,成员函数的返回值信息,它是一个参数元信息;

409,成员函数实际的调用函数对象,它是类型擦除后的函数对象;

410,成员函数的额外信息,如该成员函数在界面中如何展示或者额外的描述信息等;

411,获取成员函数名称的方法;

412,获取成员函数所属类型的类型名称;

413,获取成员函数的返回值参数元信息;

414,获取成员函数形参列表的元信息;

415,通过索引值来获取一个形参列表的参数元信息;

416,获取成员函数形参列表中参数的个数;

417,获取成员函数是否为静态成员函数;

418,设置成员函数的输出参数元信息;

419,为一个成员函数添加一个形参的参数元信息;

420,设置成员函数的静态属性值;

421,设置成员函数的类型擦除的函数对象;

422,设置成员函数的名称;

423,设置成员函数所属的类型名称;

424,实现接口begin_invoke;

425,实现接口end_invoke;

426,参数元信息的类型元信息属性;

427,参数元信息的默认值属性;

428,参数元信息的参数名属性;

429,参数元信的额外属性;

430,设置参数元信息的类型元信息属性;

431,获取参数元信息的类型元信息属性;

432,设置参数元信息的名称;

433,获取参数元信息的名称;

434,设置参数元信息的默认值属性;

435,获取参数元信息的默认值属性。

进一步地,运行时类型系统管理器和一些元编程的实用工具类数据的处理过程为:

501,类型管理器中所支持的最大类型数量;

502,数据交换栈,在类型擦除的函数调中负责传递参数和返回值;

503,存储的类型元信息实体的集合;

504,泛型接口,通过一个类型来获取类型元信息;

505,通过一个demangled类型名称来获取类型元信息;

506,通过索引值来访问一个类型元信息;

507,获取数据交换栈;

508,通过demangled名称来创建一个类元信息;

509,初始化保留类型的类型元信息,在metainfomanager创建时调用;

510,get函数的调用接口;

511,set函数的调用接口;

512,模板元函数,使用一个指向成员函数的指针来创建一个get类型擦除函数;

513,模板元函数,使用一个指向成员变量的指针来创建一个get类型擦除函数;

514,使用一个指向成员函数的指针来创建一个set类型擦除函数;

515,使用一个指向成员变量的指针来创建一个set类型擦除函数;

516,使用一个普通的数据指针来创建一个静态成员的get类型擦除函数;

517,使用一个普通的数据指针来创建一个静态成员的set类型擦除函数;

518,使用一个普通的函数指针来创建一个静态成员的get类型擦除函数;

519,使用一个普通的函数指针来创建一个静态成员的set类型擦除函数;

520,使用一个成员或者静态常量来创建一个只读类型的get类型擦除函数;

521,创建构造函数的类型擦除函数;

522,创建一个销毁器。

进一步地,用llvm工具链中的libclang,通过语法分析和用户配置表来自动生成注册代码,作为编译流程的预编译器,流程如下:

601,第一阶段使用libclang对整个项目的c++代码做词法和语法分析,分析的结果是一个抽象语法树;

602,第二阶段遍历整个语法树,将用户感兴趣的类,类中的成员方法和数据成员从语法树中萃取出来,生成用于导出的结构化数据;

603,第三阶段用结构化数据生成模板对象数据,用于模板语言的配置;

604,第四阶段生成注册类型元信息的源代码,参与项目代码的编译。

与现有技术相比本发明提供的静态强类型语言的运行时类型扩展与反射方法具有以下优点:

本发明提供了一种为静态强类型的语言扩展,在运行期保留类型信息的解决方案,在运行期可以获取对象的类型对象。可以通过类型对象获取该对象的数据成员类型对象及函数成员对象,并可以使用类型对象创建该类型的实例对象。本发明在c++编程语言的实践中,利用了部分语言特性完成了自动注册运行期类型信息的功能。并利用llvm的工具链之一libclang,在离线时完成了语言特性缺失的部分信息注册。

本发明还能够在运行期类型系统中注册用户自定义的信息,以便用户完成独特的扩展。我们的游戏引擎利用这个机制,实现了在编辑器中对数据模型的特定化展示及对数据取值范围的限定及对特定数据使用不同编辑模式等功能。

附图说明

为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。

图1为本发明实施例的基础数据类型和基础数据模型的设计类图;

图2为本发明实施例用于存储和管理任意类型数据实体,并带有详细运行期类型信息的实体对象类图;

图3为本发明实施例的类型元信息和成员变量元信息的类图;

图4为本发明实施例成员函数元信息及参数元信息的类图;

图5为本发明实施例的类型运行期管理器及运行期类型注册辅助工具的设计类图;

图6位本发明实施例的离线自动生成注册类型元信息代码的流程图。

具体实施方式

下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。

参阅图1所示,其为本发明第一实施例提供的类型扩展的数据类型和数据模型图;

在本发明的实施例是对c++语言的实现,这一套模型可以套用在任何没有静态强类型语言,并不限定于c++程序语言。

在本发明的实施例中,所述聊天组件客户端为可以运行在移动智能终端上的库、服务等应用软件。

具体而言,本发明实施例中,静态强类型语言的编译期类型萃取,通过静态强类型的编译期元编程技术,获取类型的基本信息,类型的语义和语态分析。静态强类型语言的编译期类型擦除,利用编译期元编程将不同的编译期类型用一种统一的模型描述;利用编译期元编程和函数式编程将普通的函数,成员函数,静态成员函数,仿函数及lambda表达式,用一种统一的模型来描述其函数的返回值及参数列表,并提供调用的接口。

具体而言,动态类型信息运行时管理器,管理了所有注册的运行时类型信息,并提供可观效率地运行期访问接口和类型信息注册接口。用户可以通过类型名称和类型标识符来获取类型对象。用户可以为类型对象注册成员变量及成员函数的信息,这一部分的信息利用上述两个模块自动地完成。用户还有接口可以注册额外的类型信息,解决利用语言特性无法完成的功能,例如获取成员函数参数的名称等,及用户自定义的额外信息。

具体而言,离线自动生成模块,这个模块可以自动地完成向动态类型信息运行时管理器注册类型信息的工作。它工作在编译前,是一个预编译器(pre-compiler),利用clang编译器工具链对静态强类型语言进行语法分析。它还给用户提供了一个标准的配置表,可以把用户关心的类型,成员变量和成员函数进行配置,还可以配置额外的信息。离线自动生成模块会根据语法分析出的语法树及用户的配置信息导出对应注册代码,生成的代码稍后参与项目代码的编译。

参阅图1所示,本发明实施例的基础数据类型和基础数据模型的设计类图,数据的动态类型标志符的种类表101:分别为无类型0,布尔类型1,整数类型2,浮点数类型3,字符串类型4及用户自定义类型5。数据模型联合结构体102:当类型为布尔和整数时,存储实体为num_i的64位整数;当类型为浮点数时,存储实体为num_d的浮点数;当存储类型为字符串和object的时候,存储实体是一个可以被gc回收的对象指针,名为obj;而raw_p作为扩展保留使用。

请参阅图2所示,其为本发明实施例对通用数据的结构描述的类图,类vmvalue负责存储和管理任何主语言的类型对象。

201,联合结构体用来作为访问任何类型数据实体的访问指针;

202,获取数据的动态类型标志符;

203,判断数据类型是否为无类型;

204,判断数据类型是否为整数类型;

205,判断数据类型是否为浮点数类型;

206,判断类型是否为具有算数运算的数值类型;

207,判断数据类型是否为对象类型;

208,判断数据类型是否具有值语义;

209,把数据当做布尔类型获取值,不会抛出异常,只要数据不为nil或者非空的对象都为真,反之为假;

210,将数据作为整数类型取值,若数据类型不为整数类型的兼容类型会抛出异常;

211,将数据作为字符串类型取值,若数据类型无法转换为字符串,会抛出异常;

213,将数据作为c风格字符串取值,若数据类型不是字符串类型,会抛出异常;

213,将数据作为浮点数类型取值,若数据类型不为浮点类型的兼容类型会抛出异常;

214,泛型的数据获取接口,如果t是用户自定义类型,且数据类型与用户自定义不匹配,则抛出异常;

215,判断数据类型是否为用户自定义类型;

216,将数据对象设置为nil;

217,将数据对象设置为布尔值;

218,将数据对象设置为整数值;

219,将数据对象设置为浮点数值;

220,将数据对象设置为字符串;

221,将数据对象设置为用户自定义类型的对象;

222,泛型的设置数据对象的接口;

223,创建一个空的数据对象;

224,创建一个布尔类型的数据对象;

225,创建一个整数类型的数据对象;

226,创建一个浮点类型的数据对象;

227,创建一个字符串类型的数据对象;

228,创建一个用户自定义类型的数据对象;

229,泛型的创建数据对象的接口;

230,运行时通过元数据类型创建一个默认的数据对象实体;

231,运行时通过数据类型的字符串创建一个默认的数据对象实体。

请参阅图3所示,其为本发明实施例对类型信息的元数据和类型成员数据的元数据描述的实现类图,metatypeinfo是数据类型的元信息,而metafieldinfo是数据成员的元信息,抽象类fieldaccessable是访问和设置成员变量的接口,metafieldinfo是这个接口的实现类。

301,类型元信息中这个类型的名称;

302,类型元信息中这个类型的id编号;

303,类型元信息中这个类型的所有的成员方法集合;

304,类型元信息中这个类型的所有成员变量(字段)的集合;

305,类型元信息中这个类型的构造方法;

306,类型元信息中该类型的父类类型,只支持单继承;

307,为类型元信息注册一个成员方法的接口;

308,为类型元信息注册一个成员变量的接口;

309,为类型元信息设置构造函数的接口;

310,为类型元信息设置基类类型的接口;

311,通过函数名称来获取类型元信息的成员函数元信息;

312,通过索引值来访问类型元信息成员函数元信息;

313,通过字段名称来访问字段的元信息;

314,通过索引值来访问类型元信息的字段元信息;

315,获取类型元信息的父类型元信息;

316,获取类型元信息的构造函数元信息;

317,获取类型元信息的类型名称,

318,抽象接口,用于设置成员字段的数据;

319,抽象接口,用于获取成员字段的数据;

320,字段元信息的字段名称;

321,字段元信息的所属类型名称;

322,该字段的类型元信息;

323,该字段是否是一个静态字段,而非实例字段;

324,该字段是否是只读的属性;

325,设置字段的只读属性值;

326,获取字段的只读属性值;

327,设置字段的静态属性值;

328,获取字段的静态属性值;

329,设置所属类型的类型名称;

330,获取所属类型的类型名称;

331,设置字段的名称;

332,获取字段的名称;

333,设置字段的类型元信息;

334,获取字段的类型元信息。

请参阅图4所示,其为本发明对成员方法元信和函数形参类型和返回值类型的设计类图,抽象类invocable抽象了所有的函数对象,这里就是函数类型擦除的技术要点,metamethodinfo是invocable的实现类。metaparameterinfo是参数和返回值的元信息类。

401,调用一个对象成员函数的准备阶段,它传入一个对象的实例,并返回一个数据栈,数据栈用来压入函数调用的形参列表;

402,完成一个成员函数的调用,它从数据栈中读入数据并一次传递给类型擦除前的本地函数;

403,成员函数的名称;

404,成员函数所属类型的类型元信息;

405,成员函数的类型;

406,成员函数是否是静态方法;

407,成员函数的形参列表,列表的元素是参数元信息;

408,成员函数的返回值信息,它是一个参数元信息;

409,成员函数实际的调用函数对象,它是类型擦除后的函数对象;

410,成员函数的额外信息,如该成员函数在界面中如何展示或者额外的描述信息等;

411,获取成员函数名称的方法;

412,获取成员函数所属类型的类型名称;

413,获取成员函数的返回值参数元信息;

414,获取成员函数形参列表的元信息;

415,通过索引值来获取一个形参列表的参数元信息;

416,获取成员函数形参列表中参数的个数;

417,获取成员函数是否为静态成员函数;

418,设置成员函数的输出参数元信息;

419,为一个成员函数添加一个形参的参数元信息;

420,设置成员函数的静态属性值;

421,设置成员函数的类型擦除的函数对象;

422,设置成员函数的名称;

423,设置成员函数所属的类型名称;

424,实现接口begin_invoke;

425,实现接口end_invoke;

426,参数元信息的类型元信息属性;

427,参数元信息的默认值属性;

428,参数元信息的参数名属性;

429,参数元信的额外属性;

430,设置参数元信息的类型元信息属性;

431,获取参数元信息的类型元信息属性;

432,设置参数元信息的名称;

433,获取参数元信息的名称;

434,设置参数元信息的默认值属性;

435,获取参数元信息的默认值属性;

请参阅图5所示,其为本发明对运行时类型系统管理器和一些元编程的实用工具类的设计。metainfomanager是所有类型元信息的存储和管理的位置。为了方便实现成员字段的设置和获取值的接口,metagetfunciton和metasetfunction分别是设置和获取的类型擦除函数。metahelper是一个模板元编程工具类,用c++的语言特性预先完成一些事情,例如创建类型擦除函数,静态遍历成员函数的返回值和形参列表并萃取有用的信息。

501,类型管理器中所支持的最大类型数量;

502,数据交换栈,在类型擦除的函数调中负责传递参数和返回值;

503,存储的类型元信息实体的集合;

504,泛型接口,通过一个类型来获取类型元信息;

505,通过一个demangled类型名称来获取类型元信息;

506,通过索引值来访问一个类型元信息;

507,获取数据交换栈;

508,通过demangled名称来创建一个类元信息;

509,初始化保留类型的类型元信息,在metainfomanager创建时调用;

510,get函数的调用接口;

511,set函数的调用接口;

512,模板元函数,使用一个指向成员函数的指针来创建一个get类型擦除函数;

513,模板元函数,使用一个指向成员变量的指针来创建一个get类型擦除函数;

514,使用一个指向成员函数的指针来创建一个set类型擦除函数;

515,使用一个指向成员变量的指针来创建一个set类型擦除函数;

516,使用一个普通的数据指针来创建一个静态成员的get类型擦除函数;

517,使用一个普通的数据指针来创建一个静态成员的set类型擦除函数;

518,使用一个普通的函数指针来创建一个静态成员的get类型擦除函数;

519,使用一个普通的函数指针来创建一个静态成员的set类型擦除函数;

520,使用一个成员或者静态常量来创建一个只读类型的get类型擦除函数;

521,创建构造函数的类型擦除函数;

522,创建一个销毁器。

请参阅图6所示,其为本发明的自动化解决方案,之前所属的类型系统的结构设计,最终要实施到引擎中,需要手动填写注册字段和函数或者常量等代码,这让实施难度变得成本很高。而本发明利用了llvm工具链中的libclang,通过语法分析和用户配置表来自动生成注册代码,作为编译流程的预编译器。

流程如下:

601,第一阶段使用libclang对整个项目的c++代码做词法和语法分析,分析的结果是一个抽象语法树;

602,第二阶段遍历整个语法树,将用户感兴趣的类,类中的成员方法和数据成员从语法树中萃取出来,生成用于导出的结构化数据;

603,第三阶段用结构化数据生成模板对象数据,用于模板语言的配置;

604,第四阶段生成注册类型元信息的源代码,参与项目代码的编译。

本文中应用了具体个例对本发明的原理及实施方式进行了阐述,以上实施例的说明只是用于帮助理解本发明的方法及其核心思想;同时,对于本领域的一般技术人员,依据本发明的思想,在具体实施方式及应用范围上均会有改变之处。综上所述,本说明书内容不应理解为对本发明的限制。

当前第1页1 2 3 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1