PR et PI en RPG, le prototype et l'interface de procédure
Le PR décrit un appel, le PI reçoit les paramètres. Trois exemples, chacun en RPG IV colonné et en full free : un programme qui remplace son *ENTRY PLIST par un PI, le programme qui l'appelle par son prototype, et des procédures internes. Tout a été compilé, exécuté et débogué sur un IBM i 7.5.
En une phrase
Le prototype (PR) dit à l'appelant comment appeler un programme ou une procédure ; l'interface de procédure (PI) déclare, dans l'appelé, les paramètres qu'il reçoit ; et quand les deux sont dans le même source, le compilateur vérifie qu'ils correspondent.
PR et PI, c'est quoi
En RPG III, on appelle un programme par CALL suivi de PARM, et le programme
appelé reçoit ses paramètres par *ENTRY PLIST. Rien ne vérifie que les deux listes
concordent. Le RPG IV permet les appels prototypés : on déclare l'appel une fois, et
le compilateur contrôle chaque appel.
| PR : le prototype | PI : l'interface de procédure | |
|---|---|---|
| Rôle | Décrit un appel : qui appeler, avec quels paramètres | Déclare les paramètres reçus (et la valeur rendue) |
| Où | Chez l'appelant (et, par /COPY, chez l'appelé) | Dans l'appelé : programme ou procédure |
| RPG IV colonné | Spécification D, PR en 24-25 | Spécification D, PI en 24-25 |
| Full free | DCL-PR … END-PR | DCL-PI … END-PI |
| Nom | Obligatoire ; le nom externe par EXTPGM (programme) ou EXTPROC (procédure) | Facultatif (*N en full free) ; s'il est donné, celui de la procédure, ou du prototype pour le programme principal |
| Remplace | CALL et PARM | *ENTRY PLIST et ses PARM |
Où ça s'écrit en RPG IV colonné
Le PR et le PI sont des spécifications D. La ligne qui porte PR ou PI ouvre la définition ; les lignes
suivantes, sans type de définition, sont les paramètres. Les procédures, elles, sont encadrées par
deux spécifications P : B (début) et E (fin) en colonne 24.
| Colonnes | Zone | Contenu |
|---|---|---|
| 6 | Type de spécification | D |
| 7-21 | Nom | Le nom du prototype, de l'interface ou du paramètre (indenté d'un blanc par usage) |
| 24-25 | Type de définition | PR, PI ; à blanc pour un paramètre |
| 33-39 | Longueur | Calée à droite, en 39 |
| 40 | Type de données | P condensé, S étendu, A caractère… |
| 41-42 | Décimales | Pour une zone numérique |
| 44-80 | Mots-clés | EXTPGM, CONST, VALUE, OPTIONS, VARYING… |

FD affiche la ligne de format D : Ds en 24-25, To/L jusqu'en 39, Keywords à partir de 44.En full free, plus de colonnes : DCL-PR et DCL-PI s'écrivent n'importe où sur
la ligne, les paramètres se déclarent comme des variables (packed(11:2)), et la définition
se termine par END-PR ou END-PI.
Exemple 1 Le programme appelé
Un PI à la place de *ENTRY PLIST
Le programme TVA reçoit un montant hors taxes et un taux, et rend le montant TTC dans le troisième paramètre. Son prototype est dans un membre à part, que l'appelé copie lui aussi.
RPG IV colonné Le prototype TVAPR4 et le programme TVA4
D* TVAPR4 : prototype du programme TVA4, copie (/COPY) dans
D* le programme appelant ET dans TVA4 lui-meme.
DTVA4 PR EXTPGM('TVA4')
D MONTANTHT 11P 2 CONST
D TAUX 5P 2 CONST
D MONTANTTTC 11P 2 H DFTACTGRP(*NO) DECEDIT('0,')
H* TVA4 : calcule un montant TTC. Le PI remplace *ENTRY PLIST.
/COPY QRPGLESRC,TVAPR4
DTVA4 PI
D MONTANTHT 11P 2 CONST
D TAUX 5P 2 CONST
D MONTANTTTC 11P 2
C EVAL(H) MONTANTTTC = MONTANTHT * (1 + TAUX / 100)
C EVAL *INLR = *ON
C RETURN Full free Le prototype TVAPRF et le programme TVAF
**FREE
// TVAPRF : prototype du programme TVAF, copie (/COPY) dans
// le programme appelant ET dans TVAF lui-meme.
dcl-pr tvaf extpgm('TVAF');
montantHt packed(11:2) const;
taux packed(5:2) const;
montantTtc packed(11:2);
end-pr; **FREE
// TVAF : calcule un montant TTC. Le PI remplace *ENTRY PLIST.
ctl-opt dftactgrp(*no) decedit('0,');
/copy QRPGLESRC,TVAPRF
dcl-pi tvaf;
montantHt packed(11:2) const;
taux packed(5:2) const;
montantTtc packed(11:2);
end-pi;
eval(h) montantTtc = montantHt * (1 + taux / 100);
*inlr = *on;
return; dcl-pr tvaf extpgm('TVAF');- EXTPGM fait du prototype celui d'un programme, appelé par un appel dynamique, comme un CALL. Sans EXTPGM ni EXTPROC, ce serait le prototype d'une procédure.
dcl-pi tvaf;- Le PI global est celui de la procédure principale, donc du programme. Quand un prototype existe,
le PI doit porter le même nom, et le prototype doit le précéder dans le source :
c'est le rôle du
/copyplacé avant. montantHt packed(11:2) const;- Les paramètres d'un programme sont toujours transmis par référence ; CONST interdit au programme
de les modifier.
montantTtc, sans CONST, est le paramètre de retour. *inlr = *on; return;- Le programme garde le cycle RPG : *INLR ferme le programme à la sortie.
Une compilation par programme, dans une bibliothèque qui est dans la liste des bibliothèques (le
/COPY cherche QRPGLESRC par *LIBL) :
ADDLIBLE JOBIPRPI
CRTBNDRPG PGM(JOBIPRPI/TVA4) SRCFILE(JOBIPRPI/QRPGLESRC) DBGVIEW(*SOURCE)
CRTBNDRPG PGM(JOBIPRPI/TVAF) SRCFILE(JOBIPRPI/QRPGLESRC) DBGVIEW(*SOURCE)
Exemple 2 L'appelant
Appeler un programme par son prototype
Le programme APPEL copie le même prototype, puis appelle TVA trois fois : avec des littéraux, puis avec une expression.
RPG IV colonné APPEL4
H DFTACTGRP(*NO) DECEDIT('0,')
H* APPEL4 : appelle le programme TVA4 par son prototype.
/COPY QRPGLESRC,TVAPR4
DTTC S 11P 2
DPRIX S 7P 2 INZ(12.50)
DQTE S 3P 0 INZ(3)
DTEXTE S 52A
C CALLP TVA4(100 : 20 : TTC)
C EVAL TEXTE = '100 HT a 20 % : ' + %CHAR(TTC)
C TEXTE DSPLY
C CALLP TVA4(59.90 : 5.5 : TTC)
C EVAL TEXTE = '59,90 HT a 5,5 % : ' + %CHAR(TTC)
C TEXTE DSPLY
C* CONST : on peut passer une expression
C CALLP TVA4(PRIX * QTE : 20 : TTC)
C EVAL TEXTE = '3 x 12,50 a 20 % : ' + %CHAR(TTC)
C TEXTE DSPLY
C EVAL *INLR = *ON Full free APPELF
**FREE
// APPELF : appelle le programme TVAF par son prototype.
ctl-opt dftactgrp(*no) decedit('0,');
/copy QRPGLESRC,TVAPRF
dcl-s ttc packed(11:2);
dcl-s prix packed(7:2) inz(12.50);
dcl-s qte packed(3:0) inz(3);
tvaf(100 : 20 : ttc);
dsply ('100 HT a 20 % : ' + %char(ttc));
tvaf(59.90 : 5.5 : ttc);
dsply ('59,90 HT a 5,5 % : ' + %char(ttc));
// CONST : on peut passer une expression
tvaf(prix * qte : 20 : ttc);
dsply ('3 x 12,50 a 20 % : ' + %char(ttc));
*inlr = *on; C CALLP TVA4(100 : 20 : TTC)- En colonné, l'appel prototypé passe par le code opération
CALLP, les paramètres séparés par des deux-points. En full free, on écrit simplementtvaf(100 : 20 : ttc);. tvaf(prix * qte : 20 : ttc);- Une expression en premier paramètre : c'est permis parce qu'il est CONST. Le compilateur convertit aussi 100, 59.90 ou 5.5 au format du paramètre.
decedit('0,')- La virgule décimale de
%char. Les littéraux du source gardent le point :59.90.
CALL QCMD
CALL APPEL4
CALL APPELF

Pourquoi le prototype dans un /COPY
Copié dans le programme appelé, le prototype est comparé au PI. Changeons le taux du PI
de TVAF en packed(5:3), sans toucher au prototype :
*RNF3764 30 a 000800 Définition du paramètre (P(5,3)) différente de définition
de paramètre du prototype (P(5,2)).
La compilation échoue : l'erreur est trouvée avant toute exécution. Le compilateur vérifie aussi le nom : compilé sous un autre nom que celui d'EXTPGM, le même source donne l'avertissement RNF3776 (« Programme externe du prototype de la procédure principale différent du programme en cours de création »).
Faisons maintenant l'inverse : un appelant qui recopie le prototype à la main, au lieu du /COPY, et se trompe de type pour le taux :
// Prototype recopie a la main, et faux : taux en zone (zoned)
dcl-pr tvaf extpgm('TVAF');
montantHt packed(11:2) const;
taux zoned(5:2) const;
montantTtc packed(11:2);
end-pr; APPELXF compile sans un message : le compilateur ne connaît que ce prototype-là. L'erreur n'apparaît qu'à l'exécution, dans TVAF, qui lit en condensé un taux transmis en étendu :


Un seul prototype, dans un membre copié des deux côtés : c'est ce que recommande IBM pour un programme ou une procédure appelé par d'autres programmes ou modules RPG.
Exemple 3 Les procédures
Des procédures internes, avec ou sans PR
Le programme PROC contient deux procédures : TTC, qui rend une valeur, et LIBELLE, qui a un paramètre facultatif. Elles sont dans le même source que leurs appels : le prototype est alors facultatif, le compilateur le déduit du PI.
RPG IV colonné PROC4
H DFTACTGRP(*NO) DECEDIT('0,')
H* PROC4 : deux procedures internes, sans PR (facultatif).
DTEXTE S 52A
C EVAL TEXTE = LIBELLE(TTC(100 : 20))
C TEXTE DSPLY
C EVAL TEXTE = LIBELLE(TTC(59.90 : 5.5) : 'USD')
C TEXTE DSPLY
C EVAL *INLR = *ON
P* TTC : rend une valeur ; parametres passes par VALUE
PTTC B
DTTC PI 11P 2
D HT 11P 2 VALUE
D TAUX 5P 2 VALUE
DRESULTAT S 11P 2
C EVAL(H) RESULTAT = HT * (1 + TAUX / 100)
C RETURN RESULTAT
PTTC E
P* LIBELLE : parametre facultatif, OPTIONS(*NOPASS) et %PARMS
PLIBELLE B
DLIBELLE PI 40A VARYING
D MONTANT 11P 2 CONST
D DEVISE 3A CONST OPTIONS(*NOPASS)
DDEV S 3A INZ('EUR')
C IF %PARMS >= %PARMNUM(DEVISE)
C EVAL DEV = DEVISE
C ENDIF
C RETURN %CHAR(MONTANT) + ' ' + DEV
PLIBELLE E 
P … B et P … E en colonne 24, la valeur rendue sur la ligne du PI.Full free PROCF
**FREE
// PROCF : deux procedures internes, sans PR (facultatif).
ctl-opt dftactgrp(*no) decedit('0,');
dsply libelle(ttc(100 : 20));
dsply libelle(ttc(59.90 : 5.5) : 'USD');
*inlr = *on;
// TTC : rend une valeur ; parametres passes par VALUE
dcl-proc ttc;
dcl-pi *n packed(11:2);
ht packed(11:2) value;
taux packed(5:2) value;
end-pi;
dcl-s resultat packed(11:2);
eval(h) resultat = ht * (1 + taux / 100);
return resultat;
end-proc;
// LIBELLE : parametre facultatif, OPTIONS(*NOPASS) et %PARMS
dcl-proc libelle;
dcl-pi *n varchar(40);
montant packed(11:2) const;
devise char(3) const options(*nopass);
end-pi;
dcl-s dev char(3) inz('EUR');
if %parms() >= %parmnum(devise);
dev = devise;
endif;
return %char(montant) + ' ' + dev;
end-proc; dcl-pi *n packed(11:2);- Le type écrit sur la ligne du PI est celui de la valeur rendue par
return. En colonné, c'est la longueur et le type de la ligne PI :11P 2. Le nom du PI est facultatif (*N) ; s'il est donné, c'est celui de la procédure, comme TTC en colonné. ht packed(11:2) value;- VALUE : la procédure reçoit une copie. Possible pour une procédure, pas pour un programme.
devise char(3) const options(*nopass);- Le paramètre peut manquer. On le teste avant de le lire :
%parms() >= %parmnum(devise)(IBM documente aussi%passed(devise)). dsply libelle(ttc(100 : 20));- Une procédure qui rend une valeur s'appelle dans une expression. Appelée par CALLP, sa valeur serait perdue.
CALL PROC4
CALL PROCF

Dans un programme créé par CRTBNDRPG, les procédures demandent DFTACTGRP(*NO). Compilé
avec DFTACTGRP(*YES), le même source est refusé :
RNF1520 sev 20 : La procédure ne peut pas être définie avec DFTACTGRP(*YES).
Les modes de passage des paramètres
| Mot-clé | Passage | À savoir |
|---|---|---|
(aucun mot-clé) | Par référence | L'appelé travaille sur la variable de l'appelant et peut la modifier : c'est le paramètre de retour MONTANTTTC. Il faut passer une variable de mêmes type et longueur : un packed(9:2) à la place du packed(11:2) donne RNF7535. |
CONST | Par référence, en lecture seule | L'appelé ne peut pas modifier le paramètre. On peut passer un littéral ou une expression : le compilateur crée une zone temporaire au bon format. |
VALUE | Par valeur (copie) | L'appelé reçoit une copie, qu'il peut modifier sans toucher à l'appelant. Pour les procédures seulement : interdit avec EXTPGM. |
OPTIONS(*NOPASS) | Facultatif | Le paramètre peut ne pas être passé, ainsi que tous ceux qui suivent, qui doivent aussi être *NOPASS. Tester %PARMS (ou %PASSED) avant de s'en servir. |
Sans CONST ni VALUE, un littéral est refusé. Avec le prototype de TVAF privé de CONST sur le premier paramètre, les trois appels de APPELF donnent :
*RNF7542 30 14 001400 Paramètre 1 non admis comme paramètre transmis par
référence.
Voir les paramètres reçus dans le débogueur
Un point d'arrêt sur le calcul de TVAF, puis l'appel par APPELF :
STRDBG PGM(JOBIPRPI/TVAF)
BREAK 12
CALL APPELF


EVAL montantHt : 100,00, le littéral passé par l'appelant.
EVAL montantTtc : 120,00, que l'appelant retrouve dans TTC.Les paramètres d'un PI se lisent comme des variables. CLEAR PGM enlève le point d'arrêt,
F12 laisse le programme finir, ENDDBG clôt la session.
Les erreurs, et ce qu'elles veulent dire
Toutes ont été obtenues sur un IBM i 7.5, avec les variantes fautives des exemples :
| Message | Quand | Texte | Cause |
|---|---|---|---|
RNF3764 | à la compilation de TVAF | Définition du paramètre (P(5,3)) différente de définition de paramètre du prototype (P(5,2)). | Le PI ne correspond pas au prototype copié. C'est le contrôle que l'on gagne avec le /COPY. |
RNF3776 | à la compilation, gravité 10 | Programme externe du prototype de la procédure principale différent du programme en cours de création. | Le nom de EXTPGM n'est pas celui du programme compilé. |
RNF7542 | à la compilation de l'appelant | Paramètre 1 non admis comme paramètre transmis par référence. | Un littéral ou une expression passé à un paramètre sans CONST ni VALUE. |
RNF7535 | à la compilation de l'appelant | Le type et les attributs du paramètre 3 ne correspondent pas à ceux du prototype. | Une variable d'un autre type ou d'une autre longueur passée par référence (packed(9:2) pour packed(11:2)). |
RNF1520 | à la compilation de PROCF | La procédure ne peut pas être définie avec DFTACTGRP(*YES). | Dans un programme créé par CRTBNDRPG, des procédures exigent DFTACTGRP(*NO), en CTL-OPT ou sur la commande. |
MCH1202 | à l'exécution | Erreur dans une donnée décimale (RNQ0907 : Erreur de données décimales). | Un prototype recopié à la main, faux : la compilation ne voit rien. |
Sources
Les exemples ont été compilés et exécutés sur un IBM i 7.5 (voir la méthode). Les règles viennent de ces sources, consultées le 23 octobre 2026 :
- ILE RPG Reference (SC09-2508-12), IBM, IBM i 7.5 (PDF). Prototype et interface de procédure : le PI répète le prototype et sert au contrôle ; le nom du PI doit être celui du prototype ; dans la procédure principale, le prototype précède le PI ; positions 24-25 PR et PI ; CONST (référence en lecture seule, accepte littéraux et expressions), VALUE, interdit avec EXTPGM ; OPTIONS(*NOPASS) et %PARMS, %PARMNUM, %PASSED ; prototype implicite pour une procédure du même module (CALLP).
- ILE RPG Programmer's Guide (SC09-2507-12), IBM, IBM i 7.5 (PDF). Prototype facultatif quand la procédure est dans le même module ; prototype d'une procédure appelée d'ailleurs à placer dans un membre copié dans l'appelant et dans l'appelé.
Questions fréquentes
Quelle différence entre un PR et un PI en RPG ?
Le prototype (PR, DCL-PR) décrit un appel : le nom du programme ou de la procédure et les paramètres attendus. Il sert à l'appelant. L'interface de procédure (PI, DCL-PI) déclare les paramètres que le programme ou la procédure reçoit. Elle se trouve dans l'appelé. Quand les deux sont dans le même source, le compilateur vérifie qu'ils correspondent.
Le PI remplace-t-il *ENTRY PLIST ?
Oui. Dans un programme RPG IV, un PI placé dans les définitions globales déclare les paramètres du programme, comme le faisait *ENTRY PLIST, avec en plus le contrôle par le compilateur et les mots-clés CONST et OPTIONS.
Le prototype est-il obligatoire ?
Il faut un prototype pour appeler un programme ou une procédure d'un autre module. Pour une procédure du même module, il est facultatif : le compilateur le déduit du PI. Un programme n'a pas besoin de son propre prototype ; mais les programmes RPG qui l'appellent en ont besoin, et il vaut mieux alors le mettre dans un membre /COPY, copié aussi dans le programme appelé.
Pourquoi mettre le prototype dans un membre /COPY ?
Pour que l'appelant et l'appelé compilent le même prototype. Copié dans l'appelé, il est comparé au PI : une différence donne l'erreur RNF3764 à la compilation. Recopié à la main dans l'appelant, il peut être faux sans que rien ne le signale avant l'exécution, par exemple une erreur de données décimales MCH1202.
Quelle différence entre CONST et VALUE ?
Les deux protègent la variable de l'appelant et acceptent un littéral ou une expression. CONST passe une référence en lecture seule ; VALUE passe une copie, que la procédure peut modifier. VALUE est interdit pour les paramètres d'un programme (prototype EXTPGM).
Comment rendre un paramètre facultatif ?
Avec OPTIONS(*NOPASS) sur le paramètre, et sur tous ceux qui le suivent. Dans la procédure, on teste qu'il a été passé avant de l'utiliser : %PARMS() >= %PARMNUM(nom), ou %PASSED(nom).