Методы возврата списка значений из процедуры rpgle

Я ищу метод возврата более одного значения (например, массива) из подпроцедуры в rpgle. Я не хочу использовать файлы и т. д. для хранения этого значения. Может ли кто-нибудь порекомендовать какой-либо хороший метод для достижения этого?


person Vivek    schedule 24.06.2016    source источник
comment
Нужна дополнительная информация. Насколько велик список значений? Что ты их тоже возвращаешь?   -  person Charles    schedule 24.06.2016
comment
Количество значений может варьироваться от 0 до 20. В основном эти значения будут использоваться для отображения на экране (я имею в виду подфайл).   -  person Vivek    schedule 24.06.2016
comment
Лучше отредактировать свой вопрос, включив в него любую дополнительную информацию. Таким образом, все в одном месте.   -  person Charles    schedule 24.06.2016
comment
Вы возвращаете простой тип или сложную структуру данных?   -  person Charles    schedule 24.06.2016


Ответы (3)


При возврате не более 20 значений...

Вы можете передать массив обратно напрямую.

   dcl-proc TestProc;
     dcl-pi *n char(20) dim(20) ;
       parm1 char(20);
     end-pi;

     dcl-s myarray char(20) dim(20); 

     return myarray;
   end-proc;

При желании вы можете определить процедуру как возвращающую, например, DIM(200), и передать значение того, сколько значений вы действительно хотите. Компилятор с радостью обрежет DIM(200) в DIM(20), когда вы сделаете вызов. Это дало бы немного больше гибкости. Недостатком будет производительность, если вы собираетесь вызывать это 1000 раз в секунду. Возврат "больших" значений приводит к снижению производительности.

Предполагая последнюю версию ОС, IBM добавила ключевое слово RTNPARM, чтобы повысить производительность больших возвращаемых значений.

   dcl-proc MainProc;
   dcl-s arr char(20) dim(20);
     arr = TestProc(%elem(arr));
     dsply arr(1);
   end-proc;

   dcl-proc TestProc;
     dcl-pi *n char(20) dim(200) rtnparm ;
       howmany int(10) value;
     end-pi;

     dcl-s myarray char(20) dim(200);
     dcl-s x int(10);
     for x = 1 TO howmany;
         // load array
         myarray(x) = 'Something';
     endfor;
     return myarray;
   end-proc;

Очередь данных, как упомянул Дэвид, и область данных - это другие возможности.

Они могут обеспечить большую доступность с другого языка. Но они немного сложны в использовании. К счастью, вы всегда можете предоставить оболочку, которая преобразует возвращаемый массив во что-то другое.

person Charles    schedule 24.06.2016
comment
Спасибо, у меня есть идея вернуть массив, но я немного скептически отношусь к тому, сработает ли он, если я вызову процедуру из другого модуля. Я имею в виду, что массив в процедуре является локальным, поэтому он не будет очищен, когда процедура завершится. Пардон мне, если это глупый вопрос. - person Vivek; 24.06.2016
comment
Нет, возвращаемые значения возвращаются по значению; вы не возвращаете указатель на myarray. Другими словами, за кулисами данные копируются. Дважды IIRC. Таким образом, производительность снижается при больших возвращаемых значениях. - person Charles; 25.06.2016
comment
RTNPARM меняет то, что происходит за кулисами. Но конечный результат тот же. Вы все еще не возвращаете адрес для myarray. - person Charles; 25.06.2016

Если вызываемая процедура решает, сколько элементов нужно вернуть, то при использовании механизма возвращаемого значения было бы хорошо определить возвращаемое значение как структуру данных, которая имеет массив и количество значений.

скопировать файл

dcl-c MAX_VALUES_RETURNED 20;
dcl-ds values_t qualified template;
   num int(10);
   arr char(200) dim(MAX_VALUES_RETURNED);
end-ds;
dcl-pr proc likeds(values_t) rtnparm;
 ...

звонящий

dcl-ds values likeds(values_t);
values = proc(parms);
for i = 1 to values.num;
     ... handle values.arr(i)
person Barbara Morris    schedule 26.06.2016
comment
Дополнительную информацию см. в разделе Поддержка вложенных выходных массивов в: ibm.com/developerworks/ibmi/library/ - person Christoff Erasmus; 29.06.2016

Рассмотрите возможность использования очереди данных для отправки списка значений обратно.

Процедура отправит результаты в очередь данных и вернет имя очереди данных (или ключ для очереди данных с ключом).

Затем вызывающая программа будет читать очередь данных (возможно, по ключу, если очередь уже существует) и обрабатывать записи.

Очереди данных работают быстро, легко, и у вас есть дополнительное преимущество, заключающееся в возможности использовать их с другими языками... даже если они не на IBM i (например, Java).

person David G    schedule 24.06.2016
comment
Спасибо Дэвид!! обязательно попробую это - person Vivek; 24.06.2016
comment
*DTAQ неплох, особенно из-за своей простоты. Но я бы, вероятно, использовал либо пользовательский индекс (*USRIDX), либо пользовательское пространство (*USRSPC). Все записи могут быть загружены или получены в/из *USRIDX с помощью одной операции, а *USRSPC может просто использовать указатель на него для наложения DS записей. На самом деле, я мог бы просто выделить память в вызывающей программе для желаемого количества записей, а затем передать адрес процедуре вместе с параметром, чтобы указать, сколько записей следует добавить. - person user2338816; 25.06.2016