clips系列二-clips调用外部函数

来源:互联网 发布:超次元矩阵狂三 编辑:程序博客网 时间:2024/05/22 04:52

一.在clips中声明用户定义外部函数(对应advance编程3.1节)
修改clips源码中的,userfunction.c文件中的EnvUserFunctions。
在EnvUserFunction声明的每一个自定义函数后还要调用EnvDefineFunction。
或者可以在用户自己的initialization函数中调用EnvDefineFunction,只要在clips初始化之后,自定义函数使用之前就可以。

1.

EnvDefineFunction函数形式如下:int EnvDefineFunction(environment,functionName,functionType,            functionPointer,actualFunctionName);参数:void *environment;const char *functionName, *actualFunctionName;char functionType;int (*functionPointer)(void *);

声明自定义函数的一个实例:

EnvUserFunctions函数里面这么写:void EnvUserFunctions(void *environment){/*========================================*//* Declare your C functions if necessary. *//*========================================*/extern double rta(void *);extern long long mul(void *);/*=========================================================*//* Call DefineFunction to register user-defined functions. *//*=========================================================*/EnvDefineFunction(environment,"rta",'d',PTIEF rta,"rta");EnvDefineFunction(environment,"mul",'g',PTIEF mul,"mul");}

以EnvDefineFunction(environment,”rta”,’d’,PTIEF rta,”rta”)为例
第一个参数就是函数参数里面的environment,第二个”rta”是clips函数名,代表这个函数在clips中调用时候的名字。第三个参数’d’是functionType是返回值类型,下面会列一个返回值类型对应表,第四个参数是指向函数的指针,clips名字(第二个参数)不必和真实的函数名字(第四个参数)一样。PTIEF放在函数名前面,将其转换为返回整数的函数的指针(主要是为了防止来自允许功能原型的编译器的警告)。第五个参数是第四个参数的string表示,这个和第四个参数一样,单用引号括起来。
如果函数没被成功调用EnvDefineFunction就返回0,否则就是非零值。
用户定义函数搜索优先于系统函数,所以如果用户定义了和系统中同名的函数,也会执行自定义函数,附录H中列了clips中的系统函数。

第三个参数对应的返回值类型对应表:
Return Code Return Type Expected
a External Address
b Boolean
c Character
d Double Precision Float
f Single Precision Float
g Long Long Integer
i Integer
j Unknown Data Type (Symbol, String, or Instance Name Expected)
k Unknown Data Type (Symbol or String Expected)
l Long Integer
m Multifield
n Unknown Data Type (Integer or Float Expected)
o Instance Name
s String
u Unknown Data Type (Any Type Expected)
v Void—No Return Value
w Symbol
x Instance Address
y Fact Address
bool型的,返回时候就返回0(代表false)和非零值(代表true)
String, symbol, instance name, external address, fact address, and
instance address functions这些就返回一个type void* 的指针。如果不返回值,就写v,然后也不能返回值

2.
也可以用EnvDefineFunction2函数代替EnvDefineFunction函数,来给clips提供更多的额外信息。

函数:int EnvDefineFunction2(environment,functionName,functionType,functionPointer,actualFunctionName,functionRestrictions);参数:void *environment;const char *functionName, functionType, *actualFunctionName;int (*functionPointer)(void *);const char *functionRestrictions;

多了个functionRestrictions,是一个限制条件,表明函数参数的数量和类型。
格式是: [ *]
都是数字(0-9)或者character*。
是数字就代表最少有几个参数,是*代表对参数个数不限制
是数字就代表最少有几个参数,是*代表对参数个数不限制
可选的是假设函数调用的每一个参数类型,类型对应表如下:
Type Code Allowed Types
a External Address
d Float
e Instance Address, Instance Name, or Symbol
f Float
g Integer, Float, or Symbol
h Instance Address, Instance Name, Fact Address, Integer, or Symbol
i Integer
j Symbol, String, or Instance Name
k Symbol or String
l Integer
m Multifield
n Integer or Float
o Instance Name
p Instance Name or Symbol
q Symbol, String, or Multifield
s String
u Any Data Type
w Symbol
x Instance Address
y Fact Address
z Fact address, Integer, or Symbol

一个例子:
functionRestrictions 是 “3*” 代表最少3个参数
functionRestrictions 是 “*5” 代表最多5个参数
“35n”代表最少3个最多5个参数,每个参数类型都是Integer or Float
“66fsui”代表最少6最多6就是6个参数,第一个必须是string,第三个必须是integer,因为u代表任意,i代表integer,其他的是floats(我也不懂)

二.从clips向外部函数传参

尽管函数调用后面就跟着参数,但是clips调用函数时候不带参数,参数存储在clips内部,通过调用argument access function来访问。Access functions are provided to determine both the number and types of arguments.
1.决定传递参数的数量
提供了以下几个函数:

int EnvRtnArgCount(environment);int EnvArgCountCheck(environment,functionName,restriction,count);int EnvArgRangeCheck(environment,functionName,min,max);参数:void *environment;int restriction, count, min, max;const char *functionName;

EnvRtnArgCount会返回一个整数,表示调用的函数有几个参数
EnvArgCountCheck可以用来检查是否有最小参数,最大参数或者准确的参数限制这些限制条件,只能检查一样。返回参数的个数,或者-1(代表没有满足限制条件)。第二个参数是如果没满足限制条件要在错误消息中打印的函数名。第三个参数restriction应该是NO_MORE_THAN, AT_LEAST, or EXACTLY
之一。第四个参数是一个数,也就是用来检验比较函数参数的数,和第三个参数结合起来成为限制条件。比如第三四个分别是AT_LEAST,4)应该是检验是否满足最少4个参数限制。
EnvArgRangeCheck 用来检验参数是否满足一个参数范围。如果满足条件就返回参数个数,如果没满足条件就返回-1。函数的第二个参数functionName是报错时错误消息打印的函数名,第三个参数min和第四个参数max代表参数的最大和最小个数限制。(感觉和EnvArgCountCheck没什么差别)

2.传递Symbols, Strings, Instance Names, Floats, and Integers
提供了一些可以检索Symbols, Strings, Instance Names, Floats, and Integers参数的函数

const char *EnvRtnLexeme(environment,argumentPosition);double EnvRtnDouble(environment,argumentPosition);long long EnvRtnLong(environment,argumentPosition);参数:void *environment;int argumentPosition;

EnvRtnLexeme从symbol, string, or instance name 中返回一个character指针,如果不是这些类型看返回NULL,意思是调用这个函数如果类型是这几种就返回字符串值。
EnvRtnDouble从integer或float返回数据类型返回一个浮点数,意思是调用这个函数如果类型是这几种就返回浮点数。
EnvRtnLong从integer或floatlonglong数,意思是调用这个函数如果类型是这几种就返回long long值。

因为这些函数每次都是对应的一个数,所以每次都是针对参数的一个位置,调用合适的函数,来获得对应位置的参数的值,如果是unknow类型,有其他的函数可用,在后面讨论。
另外就是EnvRtnLexeme返回的值最好自己定义一个string,然后把值拷贝过来,否则单是保存它原来的指针可能会因为垃圾回收机制使指针失效

一个例子:
这个是外部自己定义的函数

include "clips.h"/*Use EnvDefineFunction2(environment,"rta",'d',PTIEF rta,"rta","22n");*///用户定义函数,写在项目程序里,先检验是不是有两个参数,再分别取得这两个参数的值double rta(void *environment){double base, height;/*==================================*//* Check for exactly two arguments. *//*==================================*/if (EnvArgCountCheck(environment,"rta",EXACTLY,2) == -1) return(-1.0);/*===============================================*//* Get the values for the 1st and 2nd arguments. *//*===============================================*/base = EnvRtnDouble(environment,1);height = EnvRtnDouble(environment,2);/*==================================*//* Return the area of the triangle. *//*==================================*/return(0.5 * base * height);}

3.外部函数向clips返回值
4.实例

0 0
原创粉丝点击