AMXXPawn 函数

目录

1. 简介

函数(Variable)是由用户创建的标识符,能够接受输入参数,执行多条语句,并返回数值。

每个脚本至少需要拥有1个公共函数,由外界执行,否则无法编译脚本。

任何一个公共函数都可以成为脚本的入口,有了入口,才能执行运行时表达式(例如浮点数算术,或调用私有函数)。

一些需要在多个位置重复使用的代码也可以封装为函数,用不同的参数调节内部代码执行的细节。

声明、定义函数的方法有很多,

不使用关键字可以声明forward函数、脚本公共函数、插件私有函数。

使用关键字可以声明forward函数、native函数、脚本公共函数、插件私有函数、文件私有函数、备用函数。

forward函数、native函数的定义需要额外实现。

脚本公共函数、插件私有函数、文件私有函数、备用函数的定义与声明是同一条语句。

若定义main、entry函数,不允许有参数。

本接下来的声明、定义语句讲解中,()是必填项目,【】是可选项目。

2. forward函数

声明语句1:

值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (;

声明语句2:

forward)【值类型标签】 【维度声明】 (函数名称) (参数列表) 【插件状态声明】 【;

注1:

声明语句的编写者称为A。

声明语句的引用者、定义语句的编写者称为B。

注2:

【维度声明】对于A和B无意义,因为B返回数组时,A只会得到B插件的数组地址。

AMX Mod X并未提供跨插件访问变量地址的功能,而且若是栈变量,已被销毁。

注3:

插件状态声明】无意义,这是解析器的错误设计,B可以在定义语句中设定函数绑定B插件状态。

A若强行填写【插件状态声明】,会导致B的引用指令被警告,定义语句有可能报错。

A可以用AMX Mod X的dll模块或amxx插件创建、执行forward函数的转发器。这里不讨论dll模块,只讨论amxx插件。

A需引用amxmodx.inc文件,用CreateMultiForward、ExecuteForward函数创建、执行转发器。

函数声明通常应该被A写在inc文件中,供B引用,由B声明同名的公共函数,实现forward函数的定义。

当A执行转发器时,会按创建的规则执行每个B实现的公共函数。

若A不创建、执行转发器,forward函数声明没有存在意义。

总结:

主插件创建转发器,声明函数原形,其它插件定义函数,由主插件执行。

适用于制作简单的事件处理系统,跨插件通信。

3. native函数

声明语句:

native) 【值类型标签】 【维度声明】 (函数名称) (参数列表) (;

注1:

声明语句、定义语句的编写者称为A。

声明语句的引用者、函数的使用者称为B。

注2:

【维度声明】对于A和B无意义,因为A返回数组时,B只会得到A插件的数组地址。

AMX Mod X并未提供跨插件访问变量地址的功能,而且若是栈变量,已被销毁。

注3:

若该函数的定义是AMX Mod X核心模块实现的,则可以返回数组。

A可以用AMX Mod X的dll模块或amxx插件定义native函数。这里不讨论dll模块,只讨论amxx插件。

A需编写公共函数定义语句,再引用amxmodx.inc文件,用register_native函数将公共函数与native函数互相绑定。

函数声明通常应该被A写在inc文件中,供B引用,B调用native函数时,实际调用的是A定义的公共函数。

若native函数未绑定一个公共函数,B调用时会触发报错:使用了未知函数。

总结:

主插件绑定native函数声明和公共函数定义,其它插件执行native函数等于执行公共函数。

适用于制作模块化插件,主插件负责实现复杂功能,其它插件只需执行主插件暴露的函数。

4. 公共函数

声明、定义语句1:

值类型标签】 (@开头的函数名称) (参数列表) 【插件状态声明】 (函数体

声明、定义语句2:

public) 【值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (函数体

公共函数是外部模块、插件以及当前插件所有文件中皆可使用的函数。

公共函数通常是供dll模块或其它amxx插件使用,每个amxx插件都必须至少拥有1个公共函数。

当公共函数与fowrard函数同名时,该函数会被外部模块或插件调用。

当用户将公共函数名称告知其它模块或插件时,对方可调用该函数。

例如get_func_id、set_task、register_forward、menu_create等函数需要用户填写某个公共函数名称。

注1:

虽然不允许填写维度声明,但公共函数可以返回数组。

注2:

其它插件只会收到该数组在当前插件内的地址,毫无意义。

AMX Mod X并未提供跨插件访问变量地址的功能,而且若是栈变量,已被销毁。

注3:

若插件调用自己的公共函数,可以得到数组的副本。

注4:

公共函数的设计初衷是供外部调用,常需执行严格的参数检查、环境检查,不建议插件调用自己的公共函数。

注5:

当插件被暂停或停止,外部模块或插件无法调用其公共函数。

注6:

外部可以通过猜测函数id或不小心调用公共函数,导致难以预料的事情发生。

因此,若无必要,尽量用私有函数代替公共函数。

注7:

公共函数与伪公共变量不同,公共函数拥有者是插件,两个插件的同名公共函数并不是同一个公共函数。

伪公共变量的拥有者是AMX Mod X插件平台,两个插件的同名伪公共变量,会是同一个变量。

5. 文件私有函数

声明、定义语句:

static) 【值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (函数体

文件私有函数通常被称呼为静态函数,仅在当前文件可用。

例如,源码A引用了源码B(inc、sma、pawn等等),源码B内部声明了静态函数,则A或外部模块/插件无法调用这个函数。

注1:

虽然不允许填写维度声明,但静态函数可以返回数组。

毕竟这是用户自定义、自用的,所以肯定知道返回值的维度和尺寸,维度声明也就不重要了。

注2:

作为私有函数,只要用户确定参数来源安全,即可省略运行时参数检查,提高代码效率。

注3:

若无跨文件、跨插件访问的需求,应该尽量使用静态函数代替其它类型的函数。

注4:

若函数未被使用,编译时会触发警告。

6. 文件私有备用函数

声明、定义语句1:

static stock) 【值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (函数体

声明、定义语句2:

stock static) 【值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (函数体

与文件私有函数类似,但多了一个备用特性。

若该函数未被使用,编译器不会检查函数内部语法错误,不会触发未使用警告,直接舍弃。

备用函数的设计初衷是按需编译,方便函数库(inc文件)的设计,确保未使用的函数不会增加插件的文件体积。

7. 插件私有函数

声明、定义语句:

值类型标签】 (非@开头的函数名称) (参数列表) 【插件状态声明】 (函数体

插件私有函数,仅在当前插件相关的文件中可用。

例如,源码A引用源码B,源码B引用源码C,源码B内部声明了插件私有函数,则A、B、C皆可调用此函数。

注1:

虽然不允许填写维度声明,但插件私有函数可以返回数组。

毕竟这是用户自定义、自用的,所以肯定知道返回值的维度和尺寸,维度声明也就不重要了。

注2:

作为私有函数,只要用户确定参数来源安全,即可省略运行时参数检查,提高代码效率。

注3:

若有跨文件访问、无跨插件访问的需求,应该尽量使用插件私有函数代替其它类型的函数。

注4:

若函数未被使用,编译时会触发警告。

8. 插件私有备用函数

声明、定义语句:

stock) 【值类型标签】 (函数名称) (参数列表) 【插件状态声明】 (函数体

与插件私有函数类似,但多了一个备用特性。

若该函数未被使用,编译器不会检查函数内部语法错误,不会触发未使用警告,直接舍弃。

备用函数的设计初衷是按需编译,方便函数库(inc文件)的设计,确保未使用的函数不会增加插件的文件体积。

9. 值类型标签

【值类型标签】语法拆解:

【值类型标签】用于设置函数标签,约束返回值标签。

若不填写,则默认使用_:标签。

因此,下面两行代码是相同的:

static _:func() return 32;
static func() return 32;

若填写的值类型标签不存在,编译器会自动创建这个标签。

当函数与拥有不同标签的表达式做运算、或与返回值标签不同时,通常会触发编译器警告:

// 函数func拥有_标签,返回值32.0拥有Float标签,触发警告:“标签不匹配” static func() return 32.0; static CsTeams:GetTeamId(playerEntId) return CsTeams:get_user_team(playerEntId); public Player_PreThinkThink(playerEntId) { // 函数GetTeamId拥有CsTeams标签,整数字面量1拥有_标签,触发警告:“标签不匹配” if (GetTeamId(playerEntId) == 1) { } }

调用函数时,观察标签可得知函数返回值的类型,用相同标签的变量可以储存返回值。

点击查看值类型标签指南

10. 参数列表

【参数列表】语法拆解:

11. 插件状态声明

【插件状态声明】语法拆解:

【自动机声明】语法拆解:

注解:

12. 函数体

【函数体】是一个复合语句块。可以是一条表达式语句或控制流语句,或是被{}包裹的多条任意语句。

调用函数实际上就是进入函数体执行代码,完毕后退出函数体。

点击查看语句指南.html