原文: http://qlcc.blog.163.com/blog/static/44939773200785103536753/
关于AS400调用 [转]
http://www.blogone.net/user52/ccpcd/blog/36839855.html
RPGIV提供三种调用:
CALL (CALL A PROGRAM)调用一个程序,此调用又叫动态调用。
CALLP(CALL A PROTOYPED PROCEDURE OR PROGRAM)调用原型过程或者原型子过程。可以使用动态调用或者是静态调用。
CALLB(CALL A BOUND MODULE)调用一个绑定模块,此调用又叫静态调用。
CallP和CallB,Call的主要区别在于CallP提供更好的参数类型检查。它同时也提供更丰富的功能如使用值传递或者常量传递参数。
CallP是用来代替CallB和Call的。当使用CallP时,必须在D规范表中定义一个过程原型。在原型声明中,可以定义静态或者动态绑定的调用连接。关键字EXTPROC被用来指定静态调用连接,而EXTPGM被用来指定动态调用连接,(缺省是静态绑定)。
建议在进行RPG IV编程时,全部使用CallP方式以取代CALL或者CALLB调用方式。最大的好处:一是在于对程序的参数检验是在编译时进行的,这样许多参数类型、数量问题在编译时就被检查出来,实际调用的时候会减少调用程序参数出问题。二是可以使用静态调用,提高运行效率。
在使用较复杂的过程调用可以嵌套在内置函数中使用,可以省略CALLP直接在程序中使用过程名返回值。
通过定义一个相应的原型,可以容易地用CallP去调用当前使用Call或者CallB调用方式的程序。只需检查*ENTRY PLIST中定义的变量的类型并定义一个具有跟它对应类型的参数的原型。但是如果想传递变长的字符型或者数组型参数就需要指定OPTIONS(*VARSIZE)选项;如果某些参数是可选的,需要指定*PTIONS(*OMIT)或者OPTIONS(*NOPASS)选项。
一、程序内部callp子过程
1、过程原型定义: D 过程名 PR LIKE(XX)
过程参数定义
2、调用过程: RC = 过程名(参数1 :参数2 ... )
3、过程内容: P 过程名 B (过程开始,并可被外部调用)
D 过程名 PI LIKE(XX)
过程参数定义 (与上面参数定义一样)
过程体
P 过程名 E (过程结束)
4、PDM option 14
二、过程外部调用
1、外部过程书写(模块一):
过程原型定义: D 过程名 PR LIKE(XX)
过程参数定义
过程内容: P 过程名 B EXPORT (过程开始,并可被外部调用)
D 过程名 PI LIKE(XX)
过程参数定义 (与上面参数定义一样)
过程体
P 过程名 E (过程结束)
2、编译过程: PDM Option 15 或者 CrtRpgMod
3、调用过程: D 过程名 PR LIKE(XX) (过程原型定义)
(模块二) 过程参数定义
RC = 过程名(参数1 :参数2 ... )
4、PDM Option 15 或者 CrtRpgMod
CrtPgm Pgm( 模块二) Module( 模块二 模块一) ActGrp( *Caller )
(其中模块二是主模块,模块二调用模块一,生成的程序名与主模块相同)
三、调用绑定模块callb
1、被调用模块书写(模块一):
过程原型定义: D 过程1 PR
D 过程2 PR
过程内容: P 过程1 B EXPORT
D 过程1 PI LIKE(XX) (可省略)
过程参数定义 (可省略)
过程体
P 过程1 E
P 过程2 B EXPORT
D 过程2 PI LIKE(XX) (可省略)
过程参数定义 (可省略)
过程体
P 过程2 E
2、编译模块:PDM Option 15 或者 CrtRpgMod
3、调用模块书写: *Entry PLIST
PARM 变量名
callb ‘过程1’
PARM 变量名
或者:callb ‘模块一’
PARM 变量名
4、编译模块:PDM Option 15 或者 CrtRpgMod
5、生成程序:CrtPgm 程序名 Module( 模块一 模块二) ActGrp( *Caller)6、运行:Call 程序名 ( '过程1' ) ...
四、callp的使用:
1、被调用模块书写(模块一):
*Entry PLIST
PARM 变量名
模块体
2、编译模块:PDM Option 15 或者 CrtRpgMod,生成模块一。
3、调用模块书写(模块二):
变量定义
原型定义: D 模块名 PR EXTPROC('模块一')
参数定义 (此参数定义与上面变量定义一致,可用LIKE)
调用: callp 模块名(参数1 : 参数2 ...)
4、编译模块:PDM Option 15 或者 CrtRpgMod,生成模块二。或者PDM Option 14
5、生成程序:CrtPgm 程序名 LIB(模块二 模块一)(模块二为主模块,程序名可与模块二同名)
说一下三者的区别:
http://www-900.ibm.com/cn/support/viewdoc/detail?DocId=1222070000009
在CL中调用程序可以使用CALL,CALLB和CALLP三种方式。
CALL 调用OPM的老式RPG程序,采用动态内存调用方式
CALLB 调用MODULE中的PEP(primary entry procedure),此procedure不需事先声明
CALLP 调用MODULE中的procedure,此procedure必须在本程序的D specification事先声明,又称原形调用方式,和CALLB有相似的内存调用方式,但在调用之前会对调用参数进行预先检查。
目前ILE RPG中推荐使用CALLP调用内部,外部的procedure.
对程序和过程的调用
ILE程序中既可以调用程序也可以调用过程。ILE语言通过调用语句CALL和CALLP或CALLB来标识调用的目标是程序还是过程。
1.动态程序调用
使用call调用*pgm程序其实是在程序运行时将被调用的程序转换成地址,因此可以将这种方式称之为动态调用。动态程序调用包括:
A.OPM程序可以调用一个OPM程序或ILE程序
B.ILE程序可以调用一个OPM程序或另一个ILE程序
C.服务程序可以调用OPM程序或ILE程序
2.静态过程调用
使用callp调用procedure是在binding(联编)的时候将被调用的程序转换位地址,因此可以被称之为静态调用。静态调用在效率上比动态调用高。可以用静态过程调用来调用下列任何项:
A.在同一模块内的对象
B.在同一个ILE程序或服务程序内的一个单独模块中的过程
C.在一个单独的ILE服务程序中的过程
CALL, CALLB, CALLP的区别:
CALL只能调用*PGM, 是动态调用,程序运行效率低。CALLB和CALLP都只能调用PROCEDURE(怀疑一下!),大部分时候是静态调用,只有调用指针变量中所指的PROCEDURE时才是动态调用;但是CALLB不参加接口合法性检查,即:不需要原型说明,因此在运行时可能会导致一些错误。CALL 和CALLB都只能使用固定格式的实参传递,即:使用PLIST。
RPG IV中的全局变量与局部变量:
每一个OPM程序都只有一个唯一的程序入口,但是在ILE程序中每一个Procedure都可以有一个入口。在OPM程序中每一个内部子程序的变量都是全局变量,但是在ILE程序的Procedure中声明的所有变量都是局部变量,其余所有用到的变量都是全局变量。如果在Procedure中声明的变量和某一全局变量同名的话,那么这两个变量将在内存中使用不同的两个空间,也就是说这两个变量将互不影响,同名的那个全局变量将不被此procedure 使用。局部变量也将在此procedure执行完成后被全部释放。