【问题标题】:Why a program does not need to be re-compiled after changing a service program?为什么更改服务程序后不需要重新编译程序?
【发布时间】:2022-01-04 19:16:27
【问题描述】:

我试图了解服务程序如何帮助减少重新编译工作。我读过文章说,与“通过复制绑定”到程序对象中的模块不同,服务程序是“通过引用绑定”的。这就是为什么使用服务程序的程序不需要重新编译以反映更改的原因吗?

如果程序只有对服务程序的引用,那不就是一种动态绑定吗??

另外,服务程序签名是什么东西。什么时候真正改变?

【问题讨论】:

    标签: rpgle


    【解决方案1】:

    您在这里有几个问题,所以让我看看绑定。这里有两个不同的概念:通过复制绑定与通过引用绑定,以及静态与动态绑定。第一个只处理代码所在的位置。它是在程序中(通过复制绑定),还是在程序本身外部的某个地方(通过引用绑定)。在这两种情况下,调用都会跳转到其他位置来执行代码,因此在这两种情况下都使用了引用或指针,但是在通过复制绑定时,代码实际上也被复制到了程序对象中。如您所见,按引用绑定的优势在于,在按引用绑定场景中,无需重新编译所有调用者即可修改服务程序,并且新代码立即可供任何使用该服务程序的程序使用。

    接下来,静态绑定和动态绑定的区别。根据计算机科学定义,静态绑定发生在编译时,而动态绑定发生在运行时。这两种类型总是有一个参考。问题是该参考何时得到解决。也就是说,过程调用是静态的,程序调用是动态的。让我们从基础开始:

    **free
    ctl-opt Main(testcallp);
    
    dcl-pr Prog        ExtPgm('PGMA');
      parm1            Char(10) const;
      parm2            Char(10) const;
    end-pr;
    
    dcl-proc testcallp;
    
      callp Prog('1': '2');
    
    end-proc;
    

    这是一个动态调用。 PGMA 不是在编译时解析,而是在运行时callp 执行时解析。可能看起来 PGMA 是静态解析的,因为它只解析一次,但实际上,在编译这段代码时,PGMA 甚至不必存在。试一试,代码会编译成程序对象,但是执行该程序时却找不到 PGMA。因此,必须进行动态绑定。

    让我们用过程调用再试一次:

    **free
    ctl-opt DftActGrp(*No) ActGrp(*New)
            Main(testcallp);
    
    dcl-pr Proc        ExtProc('PROCA');
      parm1            Char(10) const;
      parm2            Char(10) const;
    end-pr;
    
    dcl-proc testcallp;
    
      callp Proc('1': '2');
    
    end-proc;  
    

    这次代码编译没有语法错误,但没有创建程序对象,因为它在绑定步骤上失败。找不到过程 PGMA。静态绑定。但是等等,RPG 文档说您可以使用过程指针动态调用过程。

    让我们试试吧:

    **free
    ctl-opt DftActGrp(*No) ActGrp(*New)
            Main(testcallp);
    
    dcl-pr Proc        ExtProc(Procp);
      parm1            Char(10) const;
      parm2            Char(10) const;
    end-pr;
    dcl-pr Proca       ExtProc('PROCA');
      parm1            Char(10) const;
      parm2            Char(10) const;
    end-pr;
    dcl-s Procp        Pointer(*proc) Inz(%paddr(Proca));
    
    dcl-proc testcallp;
    
      callp Proc('1': '2');
    
    end-proc;
    

    程序再次编译,没有语法错误,但在绑定步骤中挂起,因为过程 PROCA 不存在。静态绑定。即使我们可以通过交换 Procp 指向的过程来更改运行时调用的实际过程,该过程也必须在编译时存在,因为所有过程在编译时都静态绑定到程序中。

    对于binder源推荐,我只会在Barbra的回答中添加一个建议,那就是始终将模块添加到服务程序中,并且只从程序对象中引用服务程序。

    注意:有些 API 可以让您在运行时解析过程并绑定它,但这些远远超出了本文的范围。

    【讨论】:

      【解决方案2】:

      您是对的,对服务程序的调用也可以被视为“动态绑定”,但通常,“动态绑定”一词用于对程序的调用。

      服务程序的签名何时更改取决于您是否使用绑定源。如果您创建没有活页夹源 (EXPORT(*ALL)) 的 srvpgm,则签名会在有新导出时更改。如果使用活页夹源 (EXPORT(*SRCFILE)) 创建,则只有在活页夹源中的 STRPGMEXP 命令指定的签名发生更改时,签名才会更改。

      通常的建议(和我的建议)是

      • 使用活页夹源
      • 切勿更改签名
      • 始终在活页夹源末尾添加新导出

      如果签名发生变化,那么你确实需要重新编译调用程序,或者如果你已经有一个模块,至少你需要再次执行 CRTPGM。

      但是如果签名没有改变,并且导出的顺序没有改变,你应该不需要重新编译程序来获取服务程序中的变化。

      但请注意,您可能需要结束工作并开始新工作,然后您的程序才能看到服务程序的更改。旧版本的服务程序可能已经被激活到激活组中,所以它可能不会使用新版本的服务程序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-26
        • 2019-05-28
        • 2020-03-24
        • 2016-09-27
        • 1970-01-01
        • 2014-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多