ILE 环境下的各种语言(C/C++, CL, RPG, COBOL)的混合编程实例及

2024-03-27 10:40

本文主要是介绍ILE 环境下的各种语言(C/C++, CL, RPG, COBOL)的混合编程实例及,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引用: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 的混合编程

级别: 中级

饶 有清, IBM 软件工程师, IBM 中国软件开发中心
王 虎, IBM 软件工程师, IBM 中国软件开发中心

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 的编译链接过程如下图所示:


图.1
ILE 示意图 
 

通常情况下,程序只能调用用本语言编写的 Procedure,而不调用其他语言编写的 Procedure。本文将要讲述的混合编程打破了这一常规,在 ILE 环境下,通过各种语言编写的模块之间互相调用彼此的 Procedure 来实现各种语言的混合编程。例如 CL(Control Language) 编写的模块中可以调用 C/C++、RPG、COBOL 编写的 Procedure,C 语言程序中也可以调用 CL、RPG、COBOL 编写的 Procedure。

 

ILE 中的几个重要概念

在讲述混合编程之前,首先简单介绍 ILE 中的几个重要概念。

Procedure:

一段高级语言编写的 source,它可以详细地完成某项任务,然后返回给调用者。对 C 语言而言,Procedure 就是一个函数;对CL而言,Procedure 其实就是一个 CL 程序的 source。

Module:

Module 是由 ILE 编译器编译出来的,不可以执行的 Object。Module 包含有一个或多个 Procedure 和一些数据信息,以及在这个 Module 中一些 Procedure 和数据导出导入信息。当然,有些 Module 还包含调试信息,这取决于你如何编译程序。Module 的结构如下图所示:


图.2
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 的结构如下图所示:


图.3
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 的结构如下图所示:


图.4
Program 结构图 


ILE 下混合编程示例

首先分别用 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 程序源码如下:


图.5
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 的结构如下图所示:


图.6
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"信息到控制台。程序的源码如下所示:


图.7
程序源码 
 

通过 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 如下所示:


图.8
cpp 头文件 

图.9
cpp 源码 
 

用 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 如下所示:


图.9
RPG 程序 
 

用 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。


图.10
Procedure名称 
 

 

5。COBOL 程序

COBOL 程序编写的例子是把“Hello World! print by cobol!“ 消息打印出来。程序的 source 如下所示:


图.11
COBOL程序 
 

用 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 语言的格式如下:


图.12
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。


图.13
示例 
 

正是由于各种语言编写的 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 中。


图.14
C调用者源码 
 

 

在例子中,我们分别用五种语言编写了提供一个 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 一样,如下表所示:


调用各种语言编写的 Procedure 列表

C C++ CL COBOL RPG
Caller
CPRINTHELLO ProcedurePrintHello__14HelloOperationFv ProcedureCLMODULE ProcedureCBLPRINTHELLO ProcedureRPGMODULE Procedure
C
CPRINTHELLO( ) CLMODULE( )CBLPRINTHELLO( )RPGMODULE( )
C++
CPRINTHELLO( ) CLMODULE( )CBLPRINTHELLO( )RPGMODULE( )
CL
CALLPRC PRC(PRINTHELLO) CALLPRC PRC(CLMODULE )CALLPRC PRC(CBLPRINTHELLO)CALLPRC PRC(RPGMODULE)
COBOL
CALL LINKAGE TYPE IS PROCEDURE 'CPRINTHELLO' CALL LINKAGE TYPE IS PROCEDURE 'CLMODULE'CALL LINKAGE TYPE IS PROCEDURE 'CBLPRINTHELLO'CALL LINKAGE TYPE IS PROCEDURE 'RPGMODULE'
RPG
CALLB(D)'CPRINTHELLO' CALLB(D) 'CLMODULE 'CALLB(D) 'CBLPRINTHELLO'CALLB(D) 'RPGMODULE'

 



混合编程 Demo 使用

把 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。


下载

描述 名字 大小 下载方法
本文用到示例的 source
ile_sample.savf11KBHTTP
关于下载方法的信息


 

参考资料

  • ILE Concept

这篇关于ILE 环境下的各种语言(C/C++, CL, RPG, COBOL)的混合编程实例及的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/851834

相关文章

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

C语言进阶(预处理命令详解)

《C语言进阶(预处理命令详解)》文章讲解了宏定义规范、头文件包含方式及条件编译应用,强调带参宏需加括号避免计算错误,头文件应声明函数原型以便主函数调用,条件编译通过宏定义控制代码编译,适用于测试与模块... 目录1.宏定义1.1不带参宏1.2带参宏2.头文件的包含2.1头文件中的内容2.2工程结构3.条件编

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

MySQL多实例管理如何在一台主机上运行多个mysql

《MySQL多实例管理如何在一台主机上运行多个mysql》文章详解了在Linux主机上通过二进制方式安装MySQL多实例的步骤,涵盖端口配置、数据目录准备、初始化与启动流程,以及排错方法,适用于构建读... 目录一、什么是mysql多实例二、二进制方式安装MySQL1.获取二进制代码包2.安装基础依赖3.清

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

Apache Ignite缓存基本操作实例详解

《ApacheIgnite缓存基本操作实例详解》文章介绍了ApacheIgnite中IgniteCache的基本操作,涵盖缓存获取、动态创建、销毁、原子及条件更新、异步执行,强调线程池注意事项,避免... 目录一、获取缓存实例(Getting an Instance of a Cache)示例代码:二、动态