假设我有这个程序接口
d PgmText pi
d outInfo 65535
d pgmName 10 const
d pgmLibrary 10 const
我通过JTOpen
调用它,然后它读取分配给输入/输出参数outInfo
的数据。问题是%alloc
指定的数据超过了outInfo
的最大维度。
那么,我该怎么办呢?例如,我可以将AS400ByteArray
作为ProgramParameter.PASS_BY_REFERENCE
传递,但在RPG代码中我该怎么做?
注意:它必须与V5R1兼容。
v5r1?真正地
还要注意,将RPG程序中的%alloc()
数据传递回JTOpen是个坏主意。。。
你可以有一个看起来像的PI
d PgmText pi
d outInfoPtr * value
d outInfoSize 10i 0 const
d pgmName 10 const
d pgmLibrary 10 const
则使用baased
变量。。
另一种选择是将数据输出到IFS,并将文件名返回到JTOpen。
最后,如果这与调试器API的问题有关。。。你为什么要使用RPG包装?只需直接从JTOpen调用调试器API。
似乎最好的选择是用户空间。
例如,假设我们需要从*PGM
对象中提取源代码,然后从JTOpen
中读取。为了实现这一点,我们编写了以下RPG程序,该程序给定了一个*PGM
限定路径和一个*USRSPC
限定路径,并写入该用户空间。
从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