引用:http://www.ibm.com/developerworks/cn/aix/library/au-crosslanguage/index.html
ILE 环境下的各种语言(C/C++, CL, RPG, COBOL)的混合编程实例及原理简介
在 IBM System i 平台上 ILE 环境下,如何实现 C/C++, CL, RPG, COBOL 的混合编程
级别: 中级
2007 年 9 月 13 日
本文简要介绍了 IBM System i 平台上 ILE 编程原理,以及如何在 ILE 环境下实现 C/C++、COBOL、RPG 和 CL 的混合编程,在文章的结束部分给出了一个简单的 Demo。
ILE(Integrated Language Environment)
ILE 是 Integrated Language Environment 的缩写,意思为集成语言环境。ILE 是被设计用来提升 IBM System i 上程序开发的一系列工具和相关的系统支持。在 System i 平台 ILE 环境下,C/C++、CL、RPG、COBOL 语言编写的程序可以编译成 Module Object。Module Object 可以直接链接成可执行的 Program Object,也可以链接成不能直接执行的 Service Program Object,这些 Service Program Object 可以和其他的 Program Object 链接后即变成可直接执行的 Object。Object 的编译链接过程如下图所示:
通常情况下,程序只能调用用本语言编写的 Procedure,而不调用其他语言编写的 Procedure。本文将要讲述的混合编程打破了这一常规,在 ILE 环境下,通过各种语言编写的模块之间互相调用彼此的 Procedure 来实现各种语言的混合编程。例如 CL(Control Language) 编写的模块中可以调用 C/C++、RPG、COBOL 编写的 Procedure,C 语言程序中也可以调用 CL、RPG、COBOL 编写的 Procedure。
在讲述混合编程之前,首先简单介绍 ILE 中的几个重要概念。
Procedure:
一段高级语言编写的 source,它可以详细地完成某项任务,然后返回给调用者。对 C 语言而言,Procedure 就是一个函数;对CL而言,Procedure 其实就是一个 CL 程序的 source。
Module:
Module 是由 ILE 编译器编译出来的,不可以执行的 Object。Module 包含有一个或多个 Procedure 和一些数据信息,以及在这个 Module 中一些 Procedure 和数据导出导入信息。当然,有些 Module 还包含调试信息,这取决于你如何编译程序。Module 的结构如下图所示:
在 Module Object M1 中,导出了两个 Procedure(Draw_Line 和 Draw_Arc)和一个数据项(rtn_code);同时,M1 也导入一个 Procedure(Draw_Plot)。这个 Module Object 包含有一个 PEP (程序入口函数,在C中是 main 函数)和一个 UEP(Procedure Draw_Arc)。另外,Module Object M1 还包含一些调试信息。
Service Program:
Service Program 是 ILE 链接器把一个或多个 Module 链接在一起而生成的 Object。Service Program 不可以直接在 System i 上执行。从某种角度来看,System i 平台上的 Service Program 类似 Windows 平台上的 DLL(Dynamic Link Library)。Service Program 中导出的 Procedure 和数据可以被 Program 或者其他的 Service Program 调用。Service Program 的 public interface中 定义了其他 ILE Object 可以访问的 Procedure 和数据信息,我们可以通过 binder language 来定义 Service Program 的 public interface。
Service Program 一般包含有 Module 相关的数据信息,Procedure 和数据导出导入信息和调试信息。Service Program 至少有一个 UEP,没有 PEP。Service Program 的结构如下图所示:
在 SPGMEXAMP Service Program中,包含有4个 Module(M1、M2、M3和M4)。SPGMEXAMP 的 public interface 有 Procedure P3、P4 和数据项 D。P3 是在 Module M3 中定义的,P4 是在Module M4 中定义的。另外S PGMEXAMP 调用了其他 ILE Object 提供的 print Procedure。
Program:
Program 是 ILE 链接器把一个或者多个 Module Object 绑定链接而成的可以执行的 Object。Program 是由一个或多个 Module 链接而成,有时还需要链接 Service Program。Program 有且只有一个程序入口 PEP,但可以有多个 UEP。PEP 是在程序链接 CRTPGM 时,由参数 ENTMOD 来指定哪个 Module 的 PEP 为程序的 PEP。Program 的结构如下图所示:
首先分别用 CL, C/C++, RPG, COBOL 五种语言各编写一个 Module。Module 提供一个 Procedure,实现简单的打印功能,打印出 hello world! 信息。所有模块的 source 存在 /qsys.lib/ile_test.lib/mod_source.file 中,可以在后面例子中找到源代码。
1。CL(Control Language)程序
CL 编写的 Procedure 是程序把 Hello World! 消息发送到用户 RAOYQ,所以事先需要创建用户 RAOYQ。CL 程序源码如下:
使用编译命令 “CRTCLMOD MODULE(ILE_TEST/CLMODULE) SRCFILE(ILE_TEST/MOD_SOURCE) SRCMBR(CL_MODULE)“ ,在 ILE_TEST 库中生成 CLMODULE Object。使用“DSPMOD MODULE(ILE_TEST/CLMODULE) DETAIL(*PROCLIST)”命令可以查看到 Module 导出的 Procedure 情况,CL Procedure 导出的 Procedure 名称就是 Module 的名称。注意:其它 ILE object调 用这个P rocedure, 必须使用 CLMODULE 这个名称。CLMODULE 的结构如下图所示:
Module Object CLMODULE 中只导出一个 Procedure(CLMODULE);同时,Module 导入一系列系统提供的 Procedure(CEEGOTO Qcl_CHKBI、Qcl_LkLDA等)。这 个Module Object 包含有一个 PEP 和一个 UEP(CLMODULE)。
2。C程序
C 语言编写的 Procedure 是一个 C 函数,打印"Hello World! Print by C module/n"信息到控制台。程序的源码如下所示:
通过 CRTCMOD MODULE(ILE_TEST/CMODULE) SRCFILE(ILE_TEST/MOD_SOURCE) SRCMBR(C_MODULE)可以把源码编译成 Module Object。 C Procedure 导出的 Procedure 名称就是函数的名称,其它 ILE Object 调用这个 Procedure,调用函数名就可以了。如果 C Procedure 会被其他语言的 ILE Object 调用,如 CL、COBOL、RGP,Procedure 的名称必须大写,这些语言不能识别小写 Procedure 名。
3。C++ 程序
C++ 语言编写的是一个 HelloOperation 类,类中定义有一个 Procedure PrintHello。在这个 Procedure 中,"Hello World! Print by C++ module/n"被输出到 Console。HelloOperation 类定义在 /QSYS.LIB/ILE_TEST.LIB/HPP.FILE/CPP_HEADER.MBR 中,HelloOperation 实现在 /QSYS.LIB/ILE_TEST.LIB/MOD_SOURCE.FILE/CPP_MODULE.MBR 中,source 如下所示:
用 CRTCPPMOD MODULE(ILE_TEST/CPPMODULE) SRCFILE(ILE_TEST/MOD_SOURCE) SRCMBR(CPP_MODULE)命令可以把上面的 C++ Procedure 编译成 Module。由于 C++ 语言是面向对象的语言,不同于 C、CL 等面向过程的语言,所以调用 C++ 编写的 Procedure 不能直接调用 HelloOperation 类的函数成员 PrintHello,需要先创建一个对象,故在其他语言(C除外)中调用 C++写的比较困难。如果必须使用,可以用 extern “C" 来声明类 Procedure 名以避免 C++ 中的命名 mangle 问题。
4。RPG 程序
RPG 程序编写的例子是把“Hello World!”和“PRINT BY RPG”消息打印出来。程序的 source 如下所示:
用 CRTRPGMOD MODULE(ILE_TEST/RPGMODULE) SRCFILE(ILE_TEST/MOD_SOURCE) SRCMBR(RPG_MODULE) 命令可以把上面的 RPG source 编译成 Module,执行 DSPMOD MODULE(ILE_TEST/RPGMODULE) DETAIL(*PROCLIST) 命令可以查看到 Module 导出的 Procedure 情况。RPG Module 导出的 Procedure 名称如下图所示。RPG Procedure 导出的 Procedure 名称一般就是 Module 的名称,其它 ILE Object 可以直接调用这个 Procedure。
5。COBOL 程序
COBOL 程序编写的例子是把“Hello World! print by cobol!“ 消息打印出来。程序的 source 如下所示:
用 CRTCBLMOD MODULE(ILE_TEST/CBLMODULE) SRCFILE(ILE_TEST/MOD_SOURCE) SRCMBR(CBL_MODULE) 命令可以把上面的 COBOL source 编译成 Module,可以用 DSPMOD MODULE(ILE_TEST/CBL_MODULE) DETAIL(*PROCLIST) 查看到 Module 导出的 Procedure 情况,CBL Procedure 导出的 Procedure 名称是在 COBOL 程序中定义的名称,其它I LE Object 调用这个 Procedure,可以通过调用该函数名来实现。注意:如果你在 COBOL Module 中试用 STOP RUN。将导致 COBOL MODULE 停止运行,也会使外部的调用者停止运行。本文的实例就出现这个问题,可以删除该行,调用后面例子中的 make 文件 SAMPLE_MK 重新编译。
ILE 环境下,实现各种语言的混合编程的基础是:不管使用的编程语言是那一种,编译出来的 Module 都是一致的。对于 System i 系统而言,CLMODULE、CMODULE、CPPMODULE、RPGMODULE和CBLMODULE 具有 Module Object 相同的各种属性,不同的地方只有 Module 导出的函数和数据不一样。可以通过 DSPMOD 命令可以查看这些 Module 相同的和不同的各种属性。
上面由不同语言编写 Procedure 的 Module 可以通过 CRTSRVPGM 链接成 Service Program Object。链接器把这些 Module Object 的数据和 Procedure 信息都考入 Service Program Object中,数据和 Procedure 导出由 binder language 来定义。默认情况下 Service Program Object 会导出各个 Module 所导出的所有数据和 Procedure。binder language 语言的格式如下:
调用者可以直接调用 Module Object 中提供的数据和 Procedure,也可以调用 Service Program 导出的数据和 Procedure。如果外部调用者调用 Service Program 导出的数据和 Procedure 时,调用者运行时才调用导出的数据和 Procedure,既在调用者运行时才链接上 Service Program。如果外部调用者调用 Module Object 提供的数据和 Procedure,在调用者编译成 Program 时,就必须把提供数据和 Procedure 包含进调用者的 Program Object。另外,Service Program Object 可以由 binder language 来定义到处接口,而 Module Object导出则不能定义。本文使用的示例是调用 Service Program Object 提供的数据和 Procedure。
正是由于各种语言编写的 Module 的一致性,所以调用者调用其他语言编写 Module 提供的数据和 Procedure 时,就象调用本语言编写 Module 提供的数据和 Procedure 一样。C 语言中调用 CL 提供的 Procedure,直接调用 Module 或者 Service Program 提供的 Procedure,就如同调用其他 C 函数一样,编译链接时,把这个提供 Procedure 的 Object 加上就可以
下面是一个 C 调用者的程序源码,存放在 /qsys.lib/ile_test.lib/caller.file/c.mbr 中。
在例子中,我们分别用五种语言编写了提供一个 Procedure 服务的 Module。C 语言编写 Module 是 CMODULE,提供的 Procedure 是 CPRINTHELLO。C++ 语言编写 Module是 CPPMODULE,提供的是一个 HelloOperation 类。CL 语言编写 Module 是 CLMODULE,提供的 Procedure 是 CLMODULE 。RPG 语言编写 Module 是 RPGMODULE,提供的 Procedure 是 RPGMODULE 。COBOL 语言编写 Module 是 CBLMODULE,提供的 Procedure 是 CBLPRINTHELLO。下表横向项就列出了五种语言编写 MODULE 所提供的 Procedure。由于其他语言调用 C++ 编写的 Procedure 比较麻烦,我没有在表中列出具体的实现,所以用灰色表示这一列。
表竖项列出了五种语言编写的调用者。C 调用者调用 CL 提供的 CLMODULE Procedure,可以直接调用 CLMODULE( );调用 COBOL 提供的 CBLMODULE Procedure,可以直接调用 CBLMODULE( );调用 RPG 提供的 RPGMODULE Procedure,可以直接调用 RPGMODULE( )。其他语言的调用,与 C 一样,如下表所示:
CPRINTHELLO Procedure | PrintHello__14HelloOperationFv Procedure | CLMODULE Procedure | CBLPRINTHELLO Procedure | RPGMODULE Procedure |
CPRINTHELLO( ) | CLMODULE( ) | CBLPRINTHELLO( ) | RPGMODULE( ) | |
CPRINTHELLO( ) | CLMODULE( ) | CBLPRINTHELLO( ) | RPGMODULE( ) | |
CALLPRC PRC(PRINTHELLO) | CALLPRC PRC(CLMODULE ) | CALLPRC PRC(CBLPRINTHELLO) | CALLPRC PRC(RPGMODULE) | |
CALL LINKAGE TYPE IS PROCEDURE 'CPRINTHELLO' | CALL LINKAGE TYPE IS PROCEDURE 'CLMODULE' | CALL LINKAGE TYPE IS PROCEDURE 'CBLPRINTHELLO' | CALL LINKAGE TYPE IS PROCEDURE 'RPGMODULE' | |
CALLB(D)'CPRINTHELLO' | CALLB(D) 'CLMODULE ' | CALLB(D) 'CBLPRINTHELLO' | CALLB(D) 'RPGMODULE' |
把 ile_sample.savf 文件通过 FTP 传送到系统上,restore 这个文件。sample 中有一个 make 文件 SAMPLE_MK,使用 CRTBNDCL PGM(ILE_TEST/SAMPLE_MK) SRCFILE(ILE_TEST/SAMPLE_MK) SRCMBR(MK) 命令编译这个 make 文件,然后调用这个 make 文件就可以编译所有的 sample 例子了。C_CALLER.PGM 就是上面的例子,里面还有 CL_CALLER.PGM,CBL_CALLER.PGM和RPG_CALLER.PGM。
ile_sample.savf | 11KB | HTTP |
![]() | ||||
![]() | 关于下载方法的信息 | ![]() |