为什么更改服务程序后不需要重新编译程序?

Why a program does not need to be re-compiled after changing a service program?

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

如果程序只有对服务程序的引用,是不是有点动态绑定??

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

您说得对,对服务程序的调用也可以被视为“动态绑定”,但一般来说,术语“动态绑定”用于对程序的调用。

服务程序的签名什么时候改变取决于你是否使用binder源。如果您创建没有联编程序源 (EXPORT(*ALL)) 的 srvpgm,则签名会在有新的导出时更改。如果您使用活页夹源 (EXPORT(*SRCFILE)) 创建,则仅当活页夹源中 STRPGMEXP 命令指定的签名更改时,签名才会更改。

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

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

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

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

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

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

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

**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 可以让您解析过程并在 运行 时绑定它,但这些远远超出了本 post 的范围。