一.在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.实例

clips系列二-clips调用外部函数相关推荐

  1. LoadRunner如何调用外部函数

    LoadRunner如何调用外部函数 使用 VuGen 时,可以调用在外部 DLL 中定义的函数.通过从脚本调用外部函 数,可以降低脚本的内存使用量以及总体运行时间. 要调用外部函数,需要加载定义了该 ...

  2. javascript嵌套函数和在函数内调用外部函数的区别

    我们都知道在函数中定义的局部变量在声明他的函数体以及其嵌套的函数内始终是有定义的,并且在函数的作用域链上始终会有个对象指向全局对象,使函数能够访问到全局变量. var ga = 'global'; v ...

  3. python init函数可以外部调用么,如何从python类中调用外部函数

    我试图收集通过套接字解析的数据.这是我的密码:import pickle import SocketServer class SocketReciever(SocketServer.BaseReque ...

  4. python 类函数调用外部函数_python类中调用外部函数,python 函数中 定义类

    Q1:python函数里的数组如何在函数外调用出来 使用返回值的方法有两种: 可以直接把调用的函数作为变量使用 可以用调用函数给一个变量赋值 第一种情况见如下例子: l = [1,2,3,4,5] d ...

  5. ionic云开发系列二之调用webservice

    Part 1:怎么访问后台呢 在上一篇文章 ionic云开发系列一 已经介绍了在云上搭建ionic框架了,如果你还不知道怎么搭建ionic本地开发环境, 请移步ionic Getting Starte ...

  6. C语言extern调用外部函数

    > ls xuanzeSort.c common.c > cat common.c #include<stdio.h> //公共函数文件//打印long型数组的内容 void ...

  7. 验证控件jQuery Validation Engine调用外部函数验证

    在使用jQuery Validation Engine的时候,我们除了使用自带的API之外,还可以自己自定义正则验证.自定义正则验证上一篇已经讲过了,如果想使用自定义函数进行验证怎么办?其实这个控件有 ...

  8. Matlab如何调用外部函数/工具包,如何将新函数加到默认函数库中

    自从开始制作.分享工具包,我被问到最多的一个问题是: "XXX工具包怎么用?" 而我给出的回答通常是: "放在你代码文件夹,当函数调用." 什么意思呢? 方法1 ...

  9. SAP HANA SQL系列二:数据类型转换函数

    数据类型转换函数 CAST TO_ALPHANUM TO_BIGINT TO_BINARY TO_BLOB TO_CHAR TO_CLOB TO_DATE TO_DECIMAL TO_DOUBLE T ...

最新文章

  1. Apache网页优化之网页压缩
  2. Java为什么冷启动开销大?我们又该如何解决?
  3. php和python对比-PHP和Python性能比较:放弃PHP改用Python
  4. 发现了星星机这种打印工具,还挺不错...
  5. java阶乘求和正负交替_C语言程序设计课件第4章090909
  6. python定义x_Python 定义函数(示例代码)
  7. RabbitMQ Network Partitions 处理策略
  8. 从东岳流体下载自带OpenFOAM的Vmware虚拟机(Ubuntu20.04+OpenFOAM),无法共享文件夹【终极解决方案】
  9. selenium 实现循环点击_-循环点击遇到的坑(每次点击后返回,页面元素都会变化的解决方法)...
  10. 23种设计模式(5)-适配器模式
  11. CC攻击及其解决方法
  12. 学生管理系统----当然封装类型
  13. VBoxGuestAdditions.iso下载地址
  14. 签张回执单 保险合同就生效?
  15. 关于内网和外网 区别
  16. jquery 打开网页自动弹出遮罩层或点击弹出遮罩层
  17. 电脑卡死,电脑卡屏死机几个原因与解决办法必看
  18. 电影级视频剪辑PR调色/FCP调色/达芬奇调色预设LUTs
  19. Mac上Android手机无法连接解决方案
  20. Tomcat 一键启停脚本 linux

热门文章

  1. 跨域请求(使用jsonp实现跨域请求)百度地图api证逆地址解析获取周边信息(pois)
  2. Docker部署Flask网站
  3. 2、Go自动化测试入门-testify
  4. 让SOA使用者像超人一样自由
  5. 临近空间环境监测系统
  6. python使用ffmpeg去掉视频片头和片尾
  7. 与项目管理专家就软件项目管理专题探讨实录
  8. 北邮计算机专业的培养方案,现代邮政学院2016级专业培养方案-北京邮电大学.PDF...
  9. BT Dongle设计介绍
  10. SVN: an error occurred and the operation could not be completed