代码之家  ›  专栏  ›  技术社区  ›  Radinator

内部过程动态调用

  •  0
  • Radinator  · 技术社区  · 6 年前

    可能有人向我解释为什么我不能将内部过程的地址分配给一个指针,它将一个字符串变量存储在一个字符串变量中。 %paddr() BIF?

    我的想法是创建一个编号为键的关联数组,并将某个子过程的名称作为值。当用户在DSPF中输入数字2时,程序必须调用具有密钥“2”的过程。

    据我所知 %PADRD() 接受硬编码的过程名或包含过程名的字符串。但是当给出一个字符串变量时,编译器会抱怨 %PADDR 无效。

    2 回复  |  直到 6 年前
        1
  •  5
  •   jmarkmurphy    6 年前

    这是因为程序由编译器静态绑定。所以编译器需要知道编译时调用什么程序。但是,也有一些API可以用来在运行时绑定服务程序。艾伦·坎平有一些例子 here .

    让我们再谈一谈绑定。ibm i在调用程序和过程时提供两种不同类型的绑定。对于程序,绑定发生在第一次调用给定程序时的运行时,它被解析并绑定到调用方。程序名可以保存在变量中,因为程序是在运行时绑定的,所以第一次通过变量调用程序时,它将被解析并绑定到调用方,然后,当变量中的值发生更改时,程序将在下一次调用时再次解析。这称为动态绑定。绑定发生在运行时,可能是每次调用程序时,并且在调用方或激活组结束时丢失绑定。

    程序在编译时静态绑定。对于过程或过程指针,没有内置运行时绑定。您可以使用过程指针来近似动态绑定,但在内部,过程绑定到过程指针,如果通过%PADRE()提供过程指针的地址,则绑定在该点发生。甚至使用回调的API也会静态绑定。API绑定到过程指针,调用方将过程指针绑定到回调过程本身,然后将绑定传递给API。在运行时没有分辨率。你可以用这个简单的程序来测试。

    **free
    ctl-opt dftactgrp(*no) actgrp(*new) BndDir('mybnddir');
    
    dcl-s procPtr       Pointer(*proc);
    
    dcl-pr proc         ExtProc(procPtr);
    end-pr;
    
    procPtr = %paddr('MissingProcedure');
    proc();
    return;
    

    程序无法编译。它在绑定步骤中失败,因为它找不到 MissingProcedure . 但是,如果不知道回调是什么,或者它是否存在,那么它只需要绑定到程序内部的过程指针本身,就可以编译成一个参数。

    因此,rpg不提供任何在运行时(动态)绑定过程的工具,但ibm i提供了系统api,我们可以使用它手动解析服务程序中的过程。这就是我上面提到的艾伦·坎平的例子。所以从技术上说是的,我们可以动态绑定到服务程序中的过程,但是rpg不提供这样做的工具。这只发生在编译时。

        2
  •  2
  •   Mihael    6 年前

    %PADDR的参数名必须是常量,正如查尔斯和马克已经说过的。

    最简单的方法是创建一个过程指针数组。

    下面是一个小例子:

    **FREE
    
    ctl-opt main(main) dftactgrp(*no) actgrp(*caller);
    
    
    dcl-c UPPER 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    dcl-c LOWER 'abcdefghijklmnopqrstuvwxyz';
    
    
    dcl-proc main;
      dcl-pi *n;
        index char(1) const;
      end-pi;
    
      dcl-s line char(50);
      dcl-s procedureName char(256);
      dcl-s transformPtr pointer(*proc);
    
      dcl-pr transform char(50) extproc(transformPtr);
        input char(50) const;
      end-pr;
    
      dcl-s procedures pointer(*proc) dim(2);
      procedures(1) = %paddr('TOLOWER');
      procedures(2) = %paddr('TOUPPER');
    
      transformPtr = procedures(%int(index));
    
      line = 'Hello, world. =)';
      line = transform(line);
      dsply line;
    end-proc;
    
    
    dcl-proc toUpper;
      dcl-pi *n char(50);
        input char(50) const;
      end-pi;
    
      return %xlate(UPPER : LOWER : input);
    end-proc;
    
    
    dcl-proc toLower;
      dcl-pi *n char(50);
        input char(50) const;
      end-pi;
    
      return %xlate(LOWER : UPPER : input);
    end-proc;