Как преобразовать прототип функции RPGLE для вызова из программы 'C'? - PullRequest
0 голосов
/ 15 января 2019

У меня есть существующая функция RPGLE, которую мне нужно вызвать из программы C ILE. Он возвращает структуру данных, и я не могу понять, как будет выглядеть прототип C, и, следовательно, вызов будет? Я попытался извлечь суть проблемы ниже.

dcl-s idT int(10) template;

dcl-s param1T char(25) template;                                                         
dcl-s param2T char(100) template;  

dcl-ds paramT qualified template; 
  param1 like(param1T);                                               
  param2 like(param2T);
end-ds;

dcl-pr fn1 likeds(paramT);                             
  id like(idT) const;                                                   
end-pr;  

Я вижу, что входной параметр является указателем на int, поэтому у меня есть что-то вроде этого ...

paramT fn1(int *id);

Но возвращаемое значение неверно.

Я ожидаю, что значение вычисленных значений вернется в возвращенную структуру данных (отладка вызова показывает, что правильные значения * вычисляются).

EDIT: Это сторона вызова «С» (которая почти наверняка связана с проблемой).

typedef _Packed struct       
{                            
   char param1 ^25];        
   char param2 ^100];    
} paramt;    

paramt *FN1(const int *id);

paramt *value = FN1(&id);       

1 Ответ

0 голосов
/ 16 января 2019

Хотя RPGLE может получать параметры по значению или по ссылке, он всегда возвращает значение. Поэтому вы должны определить функцию следующим образом:

paramt FN1(const int *id);

и назовите это так:

paramt value = FN1(&id);

Здесь есть одна оговорка. Возвращая что-то короткое, например char (1), C любит расширять байты до целого числа, и вам может понадобиться добавить ExtProc(*cwiden) или ExtProc(*cnowiden) к вашему прототипу. Больше информации здесь .

Также существует проблема с делом. Вы правильно обработали это в своих примерах, но для полноты, RPG нечувствителен к регистру, когда дело доходит до идентификаторов. Он преобразует все в верхний регистр, если не указано иное. Это может раздражать разработчиков на C, которые любят использовать строчные буквы. Вы можете добавить *dclcase к ExtProc, чтобы указать компилятору не преобразовывать имя процедуры в верхний регистр, а вместо этого использовать регистр прототипа. Итак:

dcl-pr fn1    LikeDs(paramT) ExtProc(*dclcase);
  id          Like(idT) const;
end-pr;

Можно назвать как:

paramt value = fn1(&id);

Подробнее о *dclcase здесь .

Наконец есть RTNPARM. Это ключевое слово, которое можно добавить в процедуру RPGLE, чтобы указать, что возвращаемое значение следует рассматривать как параметр. Это может быть полезно при возврате больших строк или структур, чтобы избежать размещения большого значения в стеке. Это проблема производительности. Хотя RPGLE знает, как с этим справиться, нет способа (с помощью прототипа) сообщить программе C, что возвращаемое значение находится в первом параметре. Вам просто нужно кодировать свои прототипы C, чтобы иметь указатель на возвращаемое значение в первом расположении параметра. Подробнее о RTNPARM здесь . Многоязычный пример - CL, но вы должны понять суть.

...