从 RPG 程序返回任意二进制数据

Returning arbitrary binary data from RPG program

假设我有这个程序界面

d PgmText         pi
d  outInfo                   65535
d  pgmName                      10    const
d  pgmLibrary                   10    const

我通过 JTOpen 调用它,然后读取分配给 input/output 参数 outInfo 的数据。问题是 %alloc 化的数据超过了 outInfo.

的最大维度

那么,我该怎么办呢? 例如。我可以将 AS400ByteArray 作为 ProgramParameter.PASS_BY_REFERENCE 传递,但是我在 RPG 代码中做什么?

N.B。它必须与 V5R1 兼容。

v5r1?真的吗?

另请注意,将 RPG 程序中的数据 %alloc() 传回 JTOpen 是个坏主意 ...

你的圆周率可能看起来像

d PgmText         pi
d  outInfoPtr                       *   value
d  outInfoSize                  10i 0 const
d  pgmName                      10    const
d  pgmLibrary                   10    const

然后使用 baased 变量..

另一种选择是将数据输出到 IFS 并将 return 文件名输出到 JTOpen。​​

最后,如果这与您的调试器有关 API 问题...您为什么使用 RPG 包装器?只需直接从 JTOpen 调用调试器 APIs。

似乎最好的选择是用户 Space。

例如,假设我们需要从 *PGM 对象中提取源代码,然后我们将从 JTOpen 中读取该对象。为此,我们编写了以下 RPG 程序,给定 *PGM 限定路径和 *USRSPC 限定路径,写入该用户 Space.

从JVM层简单地ProgramCall这个RPG程序,然后用UserSpace.

读取
 h dftactgrp(*no)

  **
  * This program writes to a UserSpace with the following layout:
  *
  * Total lines number     | CHAR(10)
  * [for every line]
  *   Sequence number      | CHAR(6)
  *   Last edit date       | CHAR(6)
  *   Source line          | CHAR(*)  (lineLength - 12)
  *
  * @author Edoardo Luppi
  **

 d PgmText         pr                  extpgm('PGMTEXT')
 d  qProgramName                 20    const
 d  qUsrspcName                  20    const
 d  lineLength                   10i 0 const

 d PgmText         pi
 d  qProgramName                 20    const
 d  qUsrspcName                  20    const
 d  lineLength                   10i 0 const

  * Internal procedures
 d startSourceDebug...
 d                 pr

 d retrieveTextViewNumber...
 d                 pr            10i 0

 d retrieveViewId...
 d                 pr            10i 0
 d   viewNumber                  10i 0 value

 d writeLinesToUserSpace...
 d                 pr
 d   viewId                      10i 0 value

  /copy qcopysrc,qusrspc
  /copy qcopysrc,qdebug

 d errorCode       ds                  qualified
 d  bytesProvided                10i 0 inz(%size(errorCode))
 d  bytesAvailable...
 d                               10i 0 inz
 d  exceptionId                   7
 d                                1
 d  exceptionData               512

  * QteRetrieveModuleViews
 d vewl0100        ds                  qualified
 d  bsReturned                   10i 0 inz
 d  bsAvailable                  10i 0 inz
 d  numOfElements                10i 0 inz

 d vewl0100Element...
 d                 ds                  qualified based(vewl0100ElementPtr)
 d  moduleName                   10
 d  viewType                     10
 d  compilerId                   20
 d  mainIndicator                10
 d  viewTimestamp                13
 d  viewDescription...
 d                               50
 d                                3
 d  viewNumber                   10i 0
 d  numberOfViews                10i 0

 d vewl0100ElementPtr...
 d                 s               *

  * QteRetrieveViewText
 d textViewStruct  ds                  qualified
 d  bsReturned                   10i 0 inz
 d  bsAvailable                  10i 0 inz
 d  numOfElements                10i 0 inz
 d  lineLength                   10i 0 inz

 d textViewStructElement...
 d                 ds                  qualified based(textViewElementPtr)
 d  sequenceNum                  12
 d  sourceLine                  500

 d textViewElementPtr...
 d                 s               *

  * Common variables
 d viewId          s             10i 0 inz
 d numOfLines      s             10i 0 inz
 d returnedLib     s             10    inz
 d viewTimestamp   s             13    inz
 d receiverVar     s          32000    inz
 d textViewNumber  s              3i 0 inz
 d programName     s             10    inz
  /free

   programName = %subst(qProgramName:1:10);

   startSourceDebug();
   textViewNumber = retrieveTextViewNumber();

   if (textViewNumber >= 0);
     viewId = retrieveViewId(textViewNumber);
     writeLinesToUserSpace(viewId);
   endif;

   return;

  /end-free

  **
  * Start the debug session and register the program-stop handler exit program.
  **
 p startSourceDebug...
 p                 b
  * Program-stop handler exit program path
 d PSHEP           c                   'PGMSTOPHDLMYLIB     '
  /free

   reset errorCode;
   QteStartSourceDebug(PSHEP:errorCode);

  /end-free
 p                 e

  **
  * Find the *TEXT debug view's number.
  **
 p retrieveTextViewNumber...
 p                 b
 d                 pi            10i 0
 d i               s             10i 0 inz
  /free

   reset errorCode;

   QteRetrieveModuleViews(
     receiverVar:
     %size(receiverVar):
     'VEWL0100':
     qProgramName:
     '*PGM':
     programName:
     returnedLib:
     errorCode
   );

   vewl0100 = receiverVar;
   i = 0;

   dow (i < vewl0100.numOfElements);
     // 124 is the length of an element of the VEWL0100 structure
     vewl0100ElementPtr = %addr(receiverVar) + 12 + (i * 124);

     // We are interested in the *TEXT view only, which contains
     // sequence numbers and their associated source lines
     if (vewl0100Element.viewType = '*TEXT');
       return vewl0100Element.viewNumber;
     endif;

     i += 1;
   enddo;

   // No *TEXT view found.
   return -1;

  /end-free
 p                 e

  **
  * Get the debug View ID given its number.
  **
 p retrieveViewId...
 p                 b
 d                 pi            10i 0
 d   viewNumber                  10i 0 value

 d viewId          s             10i 0 inz
  /free

   reset errorCode;

   QteRegisterDebugView(
     viewId:
     numOfLines:
     returnedLib:
     viewTimeStamp:
     qProgramName:
     '*PGM':
     programName:
     textViewNumber:
     errorCode
   );

   return viewId;

  /end-free
 p                 e

  **
  * Writes every line of the program's source, which has a fixed width,
  * sequentially to the User Space.
  **
 p writeLinesToUserSpace...
 p                 b
 d                 pi
 d   viewId                      10i 0 value

 d data            s            999    inz
 d startLineNumber...
 d                 s             10i 0 inz(1)
 d linesPerPass    s             10i 0 inz
 d firstPass       s               n   inz(*on)
 d lineNumber      s             10i 0 inz
 d i               s             10i 0 inz
  /free

   dow firstPass or textViewStruct.bsReturned < textViewStruct.bsAvailable;
     reset errorCode;
     reset receiverVar;

     QteRetrieveViewText(
       receiverVar:
       %size(receiverVar):
       viewId:
       startLineNumber:
       linesPerPass:
       lineLength:
       errorCode
     );

     firstPass = *off;
     textViewStruct = receiverVar;

     if (textViewStruct.bsReturned < textViewStruct.bsAvailable);
       startLineNumber += textViewStruct.numOfElements;
       linesPerPass = 1000;
     endif;

     i = 0;

     dow (i < textViewStruct.numOfElements);
       // The length of an occurrence depends on lineLength
       textViewElementPtr = %addr(receiverVar) + 16 + (i * lineLength);
       data = textViewStructElement.sequenceNum +
              %subst(textViewStructElement.sourceLine:1:lineLength - 12);

       Quschgus(
         qUsrspcName:
         10 + (lineNumber * lineLength + 1):
         lineLength:
         %subst(data:1:lineLength):
         '0':
         errorCode
       );

       lineNumber += 1;
       i += 1;
     enddo;
   enddo;

   Quschgus(qUsrspcName:1:10:%char(lineNumber):'0':errorCode);

  /end-free
 p                 e