GDNative的架构从最早叫“DLScript”的时候到目前为止已经发生了很大的变化。随着Godot 3.0版本接近最终发布以及API越来越稳定,是时候对GDNative目前的形态作一个概述了。

GDNATIVELIBRARY

GDNativeLibrary是一种资源类型。它是对每种平台所需的实际二进制文件的一种抽象:包含一些属性、“入口”库加载路径清单及“入口”库所依赖库的清单。

这些清单是一套功能特性标记的简单映射形式 - 一般是一个文件路径;如果有依赖关系的话,就是一组路径。

特性标记

Godot有一套特性标记系统。特性标记表示拥有对应的特定的属性或功能,例如Windows, X11, 32, 64, mobile等等。在导出游戏时,你也可以自行定义标记,从而可能改变游戏的运行方式。

更多关于特性标记的信息,可以去http://docs.godotengine.org/en/latest/learning/workflow/export/feature_tags.html查看。

GDNativeLibrary资源中的列表由键值对形式组成,键中根据需要可以包含多个特性标记,以英文句点“.”分隔。

例如一个支持64位Linux机器的库,它的键名即“X11.64”,如果对应的是Windows的机器,则键名为“Windows.64”。

Godot编辑器提供了GUI来更人性化的进行这种资源的定义和编辑。

它会从上而下的对所有入口进行检测,并跳过那些不存在的特性标记。在所有可用的标记中,第一个会被用作入口,所以排序很重要。

SINGLETON 库

GDNativeLibrary中有一个属性是用于定义其是否支持单例形式使用的。单例库会在Godot启动期间尽可能早地载入,且会调用库中的gdnative_singleton函数。这种库常用于需要提供与Godot紧密结合的功能。

GDNATIVE

GDNative对象代表所载入的库,至于具体要加载哪个库就要从GDNativeLibrary资源文件中匹配了,Godot环境下的C++代码可以去调用该库中的函数。由于这种方式去调用函数太过灵活、底层且不安全,所以是不建议从GDScript这些脚本语言中去调的。

如果真想从脚本语言环境直接调用相应功能,可以用GDNative.call_native方法来满足需求。对于这种函数指针调用的底层细节,抽象出了一种所谓的“调用类型”来进行描述。目前仅有一种预定义调用类型:standard_varcall - 要求被调用的函数签名为 godot_variant function_name(godot_array *) 。单例库可以按需注册新的调用类型。

GDNATIVE/GODOT API

如果某个库想调用Godot的一些功能,它就需要去调用Godot的代码。而各种C++编译器之间的移植性非常有问题,所以我们选择用C语言API的形式来封装对C++的调用。这开启了多种语言访问API的可能性,但也带来了一些冗余性。

API 结构

一个库为了访问那些用C封装的函数,它首先要知道那些函数的位置。最直接的想法是留空,然后让操作系统的库加载机制来处理。

不幸的是,这种方式不能在所有平台正常运作(此处Windows可能要尴尬的咳两声),所以为了保证在所有平台设置GDNative库用同样的代码和步骤,我们决定采取另一种途径:在加载函数时,以函数指针结构(struct)的形式传递。

该结构存在于Godot中,并包含版本信息、将来的API改动字段及扩展API列表。

struct godot_gdnative_api_struct {
unsigned int type;
godot_gdnative_api_version version;
const godot_gdnative_api_struct *next;
}; struct godot_gdnative_core_api_struct {
unsigned int type;
godot_gdnative_api_version version;
const godot_gdnative_api_struct *next;
unsigned int num_extensions;
const godot_gdnative_api_struct **extensions;
// ...
};

库可以从这种struct中访问所需的函数,也就意味着不再是编写 godot_some_function();这种形式了,而是api->godot_some_function();

有些人喜欢简单的通过函数名而不是struct来访问函数,所以在有需要时,Godot的构建系统会生成一个静态库,来包裹所有的同名函数指针为静态函数。

扩展

GDNative 扩展是一种给库提供GDNative/Godot API 之外功能的方式。它们可以不同方式应用,下面会列出几种当前支持的形式的扩展。

扩展通常带有C语言API,可能还伴随着有自定义数据类型。Godot里通常有用于包裹那些和其它功能密切结合的C函数的C++类/方法。

每个扩展都有它自己的子API结构,其中包含了版本信息及未来API修改信息的字段。

ARVR

采用GDNative来实现一种VR驱动的所有API可以参考文档: file。

这套API的起点是 godot_arvr_register_interface 函数,它需要从一个单例库进行调用。那些要被Godot调用的函数则组织成一个结构以参数的形式传递过去。

目前有 null-driver 的实现、 OpenVR 的实现 和 WIP OpenHMD 的实现。

NATIVESCRIPT

GDNative的早期开发生涯里,它仅被计划用于脚本化编程,后来被发掘出更多灵活和有用的地方,脚本化编程能力现在仅仅是其中一个扩展。

NativeScript 实现了一套“脚本语言” - 在Godot中可以这么叫,但其实是用GDNative库而不是像GDScript那样的文本和文件的形式来保存相关逻辑。

NativeScript会调用库中的一个函数 nativescript_init - 告知Godot哪些类和方法是可用的。在要用到那些类和方法的时候,NativeScript就能很简单的去调用这个库来实现相应功能。

因为 NativeScript 仅对库进行操作,它并不关心这些库是用什么语言构建的,如果开发者要用自己喜欢的编程语言进行库的开发,就使得 NativeScript 成为 Godot 里的一种最佳选择,尽管在这个基础上还要付出很多努力。

那想要更灵活且更像脚本的感觉的话,就应该考虑用一下 PluginScript 了。

PLUGINSCRIPT

PluginScript也是一个扩展,它给Godot加入了封装脚本语言实现的特性。对Godot而言,它是一种运行良好且完全集成的脚本语言,但所有逻辑都是在一个库中实现的。

NativeScript 把库都当作脚本用,而PluginScript是用库来定义脚本。也就是只要在你的Godot项目中添加一些文件,就可以添加一种新的脚本语言支持。

目前为止,这种“野生”的主要应用还只有一个 godot-python项目。

与ARVR扩展类似,PluginScript的API也是非常小巧,仅有一个需要调用的函数 godot_pluginscript_register_language。该函数接受一个struct作为参数,struct里包含函数指针及脚本语言的其它信息。

Godot编辑器重启后,就能生效了。

计划

我们正在计划创建更多的扩展,如可插拔式音视频解码器。

对于GDNative当前的架构,我们已经相当满意了,下一步主要是完善文档和改善语言绑定。

[译]Godot 引擎 GDNative 架构初探的更多相关文章

  1. scrapy架构初探

    scrapy架构初探 引言 Python即时网络爬虫启动的目标是一起把互联网变成大数据库.单纯的开放源代码并不是开源的全部,开源的核心是"开放的思想",聚合最好的想法.技术.人员, ...

  2. OceanBase 架构初探

    OceanBase 架构初探 原创衣舞晨风 发布于2018-11-13 08:44:14 阅读数 1417  收藏 展开 1.设计思路 OceanBase的目标是支持数百TB的数据量以及数十万TPS. ...

  3. [译]Godot系列教程一 - 场景与节点

    场景(Scene)与节点(Node) 简介 先设想有那么一瞬间你自己不再是一名游戏开发者了,而是一名大厨! 你的装备换成了一套大厨的制服.不要考虑制作游戏的事情,你现在的职责是为你的顾客创建新的可口的 ...

  4. F2工作流引擎这工作流引擎体系架构(二)

    F2工作流体系架构概览图 为了能更好的了解F2工作流引擎的架构体系,花了些时间画了整个架构的体系图.F2工作流引擎遵循参考WFCM规范,目标是实现轻量级的工作流引擎,支持多种数据库及快速应用到任何基于 ...

  5. 云原生时代, Kubernetes 多集群架构初探

    为什么我们需要多集群? 近年来,多集群架构已经成为“老生常谈”.我们喜欢高可用,喜欢异地多可用区,而多集群架构天生就具备了这样的能力.另一方面我们也希望通过多集群混合云来降低成本,利用到不同集群各自的 ...

  6. MySQL InnoDB存储引擎体系架构 —— 索引高级

    转载地址:https://mp.weixin.qq.com/s/HNnzAgUtBoDhhJpsA0fjKQ 世界上只两件东西能震撼人们的心灵:一件是我们心中崇高的道德标准:另一件是我们头顶上灿烂的星 ...

  7. [译]Godot系列教程四 - 编写脚本

    编写脚本(Scripting) 简介 关于无需编程即可创建视频游戏的那些工具的谈论有很多.不用学习编程知识对很多独立开发者来说就是一个梦想.这种需求 - 游戏开发者.甚至在很多公司内部,希望对游戏流程 ...

  8. [译]Godot系列教程三 - 场景实例化(续)

    场景实例化(续) 要点 场景实例化带来很多便利的用法,总体来说有: 将场景细分,更便于管理 相对于某些引擎中的Prefab组件更灵活,并且在许多方面更强大 是一种设计更复杂的游戏流程甚至UI的方式 这 ...

  9. [译]Godot系列教程五 - 制作Godot编辑器插件

    制作插件 下文仅针对2.1版本. 关于插件 插件是为编辑器扩展出更多有用工具的重要方式.它可以完全用GDScript和标准场景开发,甚至都不需重新加载编辑器就可生效.不像模块,你无需创建C++代码.也 ...

随机推荐

  1. Winform给TextBox设置默认值

    Winform给TextBox设置默认值(获取焦点后默认值消失) 主要是通过TextBox的获取焦点Enter和失去焦点Leave两个事件来实现的, 思路如下: 1.设置一个字符串常量,作为TextB ...

  2. BZOJ.4653.[NOI2016]区间(线段树)

    BZOJ4653 UOJ222 考虑二分.那么我们可以按区间长度从小到大枚举每个区间,对每个区间可以得到一个可用区间长度范围. 我们要求是否存在一个点被这些区间覆盖至少\(m\)次.这可以用线段树区间 ...

  3. Python3练习题系列(06)——各种符号总结

    Python3中的各种符号总结 1关键字 import keyword print(keyword.kwlist, end='\t') ['False', 'None', 'True', 'and', ...

  4. 2016年3月4日Android实习笔记

    1.让水平LinearLayout中的两个子元素分别居左和居右 在LinearLayout中有两个子元素,LinearLayout的orientation是horizontal.需要让第一个元素居左, ...

  5. ssm数据库中文乱码问题

    (1)详解Spring中的CharacterEncodingFilter--forceEncoding为true    <a href="http://www.cnblogs.com/ ...

  6. python 条件语句和基础数据类型

    条件语句 if 条件: pass else: pass 如果1等于1,输出欢迎进入东京热,否则输出欢迎进入一本道 ==: print("欢迎进入东京热") else: print( ...

  7. POI HSSFCellStyle 设置 Excel 单元格样式

    POI中可能会用到一些需要设置EXCEL单元格格式的操作小结: 先获取工作薄对象: HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...

  8. java实现八种排序算法并测试速度

    速度测试: (1) 随机数范围:0-100希尔排序: => Time is 38600基数排序: => Time is 53300快速排序: => Time is 46500堆  排 ...

  9. 【T01】理解面向连接和无连接协议之间的区别

    1.面向连接和无连接指的是协议,本质区别在于:对于无连接协议来说,每个分组的处理都独立于其他的分组. 而对于面向连接的协议,协议实现维护了当前分组与后继分组有关的状态信息. 2.无连接就是指udp,分 ...

  10. Python:提取网页中的电子邮箱

    import requests, re #regex = r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"#这个正则表达式过滤 ...