AngelScript基础用法:注册函数

DinS          Written on 2018/1/15

文本介绍如何在AS中注册并调用函数,确保阅读过《AngelScript框架介绍》。

现在再次回顾一下使用脚本的动机。
我们想要把逻辑部分从代码中剥离,这样不需要重新编译只要更换文本就可以实现逻辑变化。为了达到代码与脚本的交互,有几个方面的事情需要脚本引擎提供:
第一种是函数的交互,脚本中可以使用代码的函数,代码中可以调用脚本的函数;
第二种是类的交互,脚本中可以使用代码的类,代码中可以调用脚本的类;
第三种是数据的交互,包括基本数据类型的交互和自定义类的交互;

在基础篇中,我们先来研究使用基本数据类型的函数交互。
注:为了简化代码方便理解,示例中除了message callback外都不处理错误了。

让我们看一看上个helloworld例子中我们是如何注册代码中的函数的。

大图点这里

第一个参数相当于函数签名,包括了返回值、名称和参数。本来脚本只支持原始数据类型,比如int,float,double,bool,void。但是我们注册了字符串,所以string可以被脚本识别。当然关于字符和字符串需要深入讲解,后面再说。另外char在脚本里并不是基本数据类型。另一个问题涉及到引用,这里暂且忽略。
第二个参数是函数指针,当然为了方便调用AS提供了宏来处理。asFUNCTION用于注册没有重载的函数,asFUNCTIONPR用于注册有重载的函数,具体使用方法见http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_func.html。
第三个参数是调用约定,c++一般都是cdecl,所以一般用这个可以。对于显式声明为stdcall的函数用asCALL_STDCALL。

为了更加贴近现实,让我们制作一个稍微复杂一点的函数,并注册。

这个函数应该具有代表性,涵盖了int和double,并且内容涉及了复杂的类,功能就是模拟投骰子。下面看主函数内容。

大图点这里

脚本中的函数如下:

有几点需要注意。
首先是注册函数的写法,第一个参数就是函数声明,一模一样。
其次是获取脚本函数的写法,参数是脚本内函数的声明,一模一样。
最后是如何传参和获取返回值。我们通过context与脚本交互,使用context的成员函数SetArg…和GetReturn…完成脚本函数交互。参数的设置一定要在Prepare之后Execute之前。
Set的第一个参数指明脚本中对应的第几个参数(从0开始),后面那个是实际的值。更具体的说明可见http://www.angelcode.com/angelscript/sdk/docs/manual/doc_call_script_func.html。

运行结果:

如果把第一个参数改成2.5,第二个参数改成7.7,再次运行:

这说明脚本中的if-else和判断是有效的,其调用的RollDice也是有效的。

现在我们掌握了函数交互和基本数据类型,可以再次理解什么是AS了,见下图 :

AS的脚本引擎相当于一个解释器,这个解释器一开始只知道基本数据类型,我们需要给解释器喂入新的符号,这样解释器一旦在脚本中遇到这个符号就知道其所指。
喂完符号后为了运行脚本,引擎会创建一个context,脚本只在这个context里运行,通过context提供的接口与程序交互。
运行脚本应该是一行一行执行,遇到符号就查询解释器,如果没有就出错。
目前为止我们接触的脚本都是一个函数,一般而言这个足够了,因为脚本的目的就是把逻辑剥离出程序,这个逻辑一般都是一个切片slice,方便随时更换。当然可以包含多个函数和类,实际上脚本内可以#include,不过这些是后话了。
以上就是对AS的一个深入理解,希望读者深刻理解这个模型。

不过问题还是存在的,现在脚本只能够处理基本数据类型,这大大限制了其功能,甚至可以说都没法用,太原始。我们希望能够将自定义的类放入脚本中执行,如果这个能够实现,就可以大大扩展脚本能力。这个是可以做到的,这也是使用AS的一大动机,见《AngelScript进阶用法:在脚本中使用代码类》。