C -> 大型机上的 COBOL 跨语言通信

Posted

技术标签:

【中文标题】C -> 大型机上的 COBOL 跨语言通信【英文标题】:C -> COBOL interlanguage communication on mainframe 【发布时间】:2016-11-02 22:30:47 【问题描述】:

在大型机上用 C 语言编写的供应商软件包提供了通过用户出口覆盖其部分功能的选项。提供的 C 函数原型为:

extern int SomeExit (void * Parameters,
                     void * Record1,
                     void * Record2,
                     char ComparisonType,
                     char * RankString,
                     void * NotUsed1,
                     int * NotUsed2)

由于我们主要是一家 COBOL 商店,因此我定义了一个 Enterprise COBOL 4.2 程序(作为 DLL)来实现出口,试图遵循 IBM ILC 指南 (https://www.ibm.com/support/knowledgecenter/en/SSLTBW_1.13.0/com.ibm.zos.r13.ceea400/clcccb5.htm#clcccb5) 中给出的约定以及这个旧 SHARE 演示文稿中的示例:http://www-01.ibm.com/support/docview.wss?uid=swg27003846&aid=1 但生成的程序在调用退出时异常终止,并且在我的DISPLAY 消息之前。我的假设是我没有正确声明接收数据结构。下面是我当前测试代码的 sn-p (忽略我的命名约定 - 这是一个原型,用于证明接口,一旦我有基本的调用工作,将重写为我们的内部标准)。

IDENTIFICATION DIVISION.   
PROGRAM-ID.    "SomeExit". 
...
LINKAGE SECTION.                                               
01  WS-PARAMETERS-POINTER       USAGE IS POINTER SYNCHRONIZED. 
01  SORT-PASS-RECORD1-POINTER   USAGE IS POINTER SYNCHRONIZED. 
01  SORT-PASS-RECORD2-POINTER   USAGE IS POINTER SYNCHRONIZED. 
01  WS-COMPARISION-TYPE         PIC X.
01  WS-RANK-STRING-POINTER      USAGE IS POINTER SYNCHRONIZED. 
01  WS-NOT-USED1-POINTER        USAGE IS POINTER SYNCHRONIZED. 
01  WS-NOT-USED2-POINTER        USAGE IS POINTER SYNCHRONIZED. 
01  WS-RETURN                   PIC S9(9) USAGE IS BINARY.
...
PROCEDURE DIVISION USING BY VALUE WS-PARAMETERS-POINTER     
                     SORT-PASS-RECORD1-POINTER          
                     SORT-PASS-RECORD2-POINTER          
                     WS-COMPARISION-TYPE                
                     WS-RANK-STRING-POINTER             
                     WS-NOT-USED1-POINTER               
                     WS-NOT-USED2-POINTER               
               RETURNING WS-RETURN.                     

DISPLAY 'IN EXIT'.
... 
MOVE 0 TO WS-RETURN.
GOBACK.

异常结束是:

CEE3250C The system or user abend U 016 R=00000000 was issued.                                                     
     From entry point main at compile unit offset +00000192 at entry offset +00000192 at address 28500ECA.     

供应商代码动态调用 DLL。当我删除 DLL 时,我收到一条消息,指出找不到出口,因此 C 代码似乎正在尝试调用它。

我尝试了PROCEDURE DIVISION USING 的变体,包括删除BY VALUE,使用BY REFERENCE(虽然我知道这是默认设置)并用实际的结构定义替换POINTERs。我是否误解了有关如何构造传递给 COBOL 例程的参数的手册?

编辑:我确实向供应商开放了支持票,但他们尚未回复任何有用的信息。

谢谢,大卫

【问题讨论】:

什么异常?什么程序中的什么位移?为什么BY VALUE 对于所有内容,我只考虑比较类型,其他通过引用?你知道那是做什么的吗?忘记SYNCHRONIZED。为什么为您的 LINKAGE SECTION 项目添加 WS- 前缀?严格来说,您应该始终在 GOBACK 之前将 WS-RETURN 设置为某个值。哪个版本的企业 COBOL?来自 C 的调用是否来自 DLL?您是否询问过供应商(您的许可包括支持)。 一小时内查看了 23 次,获得了 2 次点赞。这是一个哇!对于 COBOL 问题。可能意味着比 COBOL 人阅读更多的 C,比 Mainframe 更多的非 Mainframe :-) 你的PROGRAM-ID 是什么?出口是静态链接还是供应商例程 fetching 你的 cobol-dll? 谢谢。 From entry point main 表示异常结束来自 C(或 C++)程序,因为 Enterprise COBOL 没有“main” - 如果它是您的程序中的异常结束,则此时会显示 SomeExit。它是用户异常终止,代码为 16。用户异常终止是特定于应用程序的。您正在运行的产品已生成异常结束。这意味着它已将某些内容识别为不正确,并且该不正确是最终的。检查所有假脱机文件(从第三个开始),因为可能有(也可能没有)附加消息。 因为你的模块根本不存在,你会失败(尽管哪个异常结束代码?S806?)@piet.t 关于出口是否应该是静态链接的观点值得确认在退出的文档中。对于 POINTER 项目,请使用 BY REFERENCE。另一方面,您可以使用 BY VALUE。我认为您可以将 RETURNING 项目保持原样。我无法想象那里的任何变化都会影响异常结束。您知道供应商代码是否为 64 位吗?如果是,请忘记使用 COBOL 程序。# 【参考方案1】:

感谢 cmets,我能够根据 Bills 的建议更好地理解调用结构,从而确定解决方案。给定这个 C 原型:

extern int SomeExit (void * Parameters,
                     void * Record1,
                     void * Record2,
                     char ComparisonType,
                     char * RankString,
                     void * NotUsed1,
                     int * NotUsed2)

解决办法:

IDENTIFICATION DIVISION.     
PROGRAM-ID.    "SomeExit".   
...
LINKAGE SECTION.      
01  WS-PARAMETERS        PIC X(10).    
01  SORT-PASS-RECORD1    PIC X(50).    
01  SORT-PASS-RECORD2    PIC X(50).    
01  WS-COMPARISON-TYPE   PIC X.
01  WS-RANK-STRING       PIC X(6).                  
01  WS-NOT-USED1         PIC X.                     
01  WS-NOT-USED2         PIC X.                     
01  WS-RETURN            PIC S9(9) USAGE IS BINARY.
... 
PROCEDURE DIVISION USING                     
        BY REFERENCE WS-PARAMETERS       
        BY REFERENCE SORT-PASS-RECORD1   
        BY REFERENCE SORT-PASS-RECORD2   
        BY VALUE     WS-COMPARISON-TYPE  
        BY REFERENCE WS-RANK-STRING      
        BY REFERENCE WS-NOT-USED1        
        BY REFERENCE WS-NOT-USED2        
           RETURNING WS-RETURN.          
    DISPLAY 'IN EXIT'.
    ... 
    MOVE 0 TO WS-RETURN.
    GOBACK.

通过上述方式,成功调用了用户出口并向供应商逻辑返回了一个值。我使用以下参数编译RENT, TRUNC(BIN), DLL,EXPORTALL 和链接DYNAM(DLL),RENT。我的应用程序不需要,但如果调用程序在上述示例解决方案中使用的被调用程序中需要混合大小写的例程名称,则还需要 PGMNAME(LONGMIXED)

感谢所有评论者为我指明正确的方向。

【讨论】:

感谢您发布解决方案。我之前没有注意到...。如果你有使用参数的代码,你会在某个地方破坏一些东西。您只是没有看到 DISPLAY 的输出(没有 SYSOUT DD?)?还是 compile/linkedit/binder 选项修复了异常结束?无论如何,干得好。 @BillWoodger 是的......引用了读取参数的逻辑(但没有更新它们),但与我遇到的问题无关。在我做出改变之前,它没有进入显示语句。

以上是关于C -> 大型机上的 COBOL 跨语言通信的主要内容,如果未能解决你的问题,请参考以下文章

古老的编程语言仍然对大公司至关重要。但没人想学习它们, COBOL编程语言

古老的编程语言仍然对大公司至关重要。但没人想学习它们, COBOL编程语言

如何在大型机 COBOL 中“休眠”?

COBOL 程序不会在我的报告中输出详细信息行

cobol 英文资料

Cobol 大型机 - 执行不同的索引 - 显示