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. Java—集合框架详解

    一.描述Java集合框架 集合,在Java语言中,将一系类的对象看成一个整体. 首先查看jdk中的Collection类的源码后会发现Collection是一个接口类,其继承了java迭代接口Iter ...

  2. UC浏览器中Ajax请求中传递数据的一个坑

    今天突然收到一个bug,有用户在其浏览器环境中一直无法提交内容,使用的是UC浏览器.当换成Chrome时,内容能够正常提交.鉴于本地没有一直使用Firefox 以及Chrome,于是去下载了一个UC ...

  3. C/C++指针参数赋值问题

    今天遇到一个问题,即在C/C++中,关于在函数里对指针赋值的问题.首先可以看到如下现象: void test(int *p) { p = NULL; } int main(int argc, char ...

  4. 码云 使用 汉化 GitHub

    enhancement 增强feature 功能duplicate 重复的invalid 无效的wontfix 无法修改 不处理 ===== Wiki 主要是您项目的文档(说明, 状态)等等. 该项目 ...

  5. Scratch儿童项目式编程--接球游戏 Scratch children program programming - catching a ball

    Scratch儿童项目式编程--接球游戏 Scratch children program programming - catching a ball 作者:韩梦飞沙 Author:han_meng_ ...

  6. loj#2574. 「TJOI2018」智力竞赛 (路径覆盖)

    目录 题目链接 题解 代码 题目链接 loj#2574. 「TJOI2018」智力竞赛 题解 就是求可重路径覆盖之后最大化剩余点的最小权值 二分答案后就是一个可重复路径覆盖 处理出可达点做二分图匹配就 ...

  7. 洛谷P2105 K皇后

    To 洛谷.2105 K皇后 题目描述 小Z最近捡到了一个棋盘,他想在棋盘上摆放K个皇后.他想知道在他摆完这K个皇后之后,棋盘上还有多少了格子是不会被攻击到的. (Ps:一个皇后会攻击到这个皇后所在的 ...

  8. Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) 题解【ABCDE】

    A. Vicious Keyboard 题意:给你一个字符串,里面只会包含VK,这两种字符,然后你可以改变一个字符,你要求VK这个字串出现的次数最多. 题解:数据范围很小,暴力枚举改变哪个字符,然后c ...

  9. 增益 Gain 分贝 dB

    https://zh.wikipedia.org/wiki/%E5%88%86%E8%B2%9D 分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用dB表示. “分” ...

  10. AngularJS中监视Scope变量以及外部调用Scope方法

    在AngularJS中,有时候需要监视Scope中的某个变量,因为变量的改变会影响一些界面元素的显示.有时,也希望通过jQuery调用Scope的某个方法. 比如以下场景: <div> & ...