Ibm midrange 内部过程的动态调用

Ibm midrange 内部过程的动态调用,ibm-midrange,rpgle,Ibm Midrange,Rpgle,有人能解释一下为什么我不能用%paddr()BIF将存储在字符串变量中的内部过程的地址分配给ProcPointer吗 我的想法是创建一个关联数组,以数字作为键,以某个子过程的名称作为值。当用户在DSPF中输入数字2时,程序必须调用具有键“2”的过程 据我所知,BIF%paddr()要么采用硬编码过程名称,要么采用包含过程名称的字符串。但是当给出一个字符串变量时,编译器会抱怨%PADDR的参数无效。这是因为程序是由编译器静态绑定的。因此,编译器需要在编译时知道调用哪个过程。但是,有一些API可用于

有人能解释一下为什么我不能用
%paddr()
BIF将存储在字符串变量中的内部过程的地址分配给ProcPointer吗

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


据我所知,BIF
%paddr()
要么采用硬编码过程名称,要么采用包含过程名称的字符串。但是当给出一个字符串变量时,编译器会抱怨
%PADDR
的参数无效。

这是因为程序是由编译器静态绑定的。因此,编译器需要在编译时知道调用哪个过程。但是,有一些API可用于在运行时绑定服务程序。艾伦·坎平有一些例子

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

过程在编译时是静态绑定的。过程或过程指针没有内置的运行时绑定。您可以通过使用过程指针近似动态绑定,但在内部,过程绑定到过程指针,如果您通过%paddr()为过程指针提供地址,则绑定将在该点发生。甚至使用回调的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
。但是,希望接收回调作为参数的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;

因此,RPG不提供任何工具来在运行时(动态)绑定过程,但IBMi提供了系统API,我们可以使用它来手动解析服务程序中的过程。这就是我上面提到的Alan Campin的例子所做的。所以从技术上讲,我们可以动态绑定到服务程序中的过程,但RPG不提供这样做的工具。这只发生在编译时。

正如Charles和Mark所说,%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;

显示您的代码…过程调用通常在编译时绑定,除非您使用的是过程指针。我认为OP的问题在于%PADDR不是动态的。但他当然可以使用%PADDR来构建指向现有内部过程的指针数组……我相信该过程在编译时仍然是绑定的。它绑定到过程指针,而不是调用操作。
%paddr()
的目标必须是常量或原型名称。@事实上,我知道它是在编译时绑定的。使用过程指针运行程序不需要绑定目录,因为绑定发生在编译时。它不在编译时绑定,因为PGMA在运行时调用的过程在编译PGMA时甚至不必存在。例如,设计用于使用回调的程序/过程。@设计用于使用回调的API不会将回调绑定到其中。使用回调的API调用方将回调绑定到它,并将该绑定传递给回调的用户。运行时未发生绑定。%paddr()使过程静态绑定到它所在的程序。如果缺少%paddr()的目标,则无法编译程序,绑定步骤将失败。