Les versions 3.60 et 3.20 apportent à RPG-IV un nouvel ordre, CALLP. il permet de faire des appels de programmes en format libre il faut pour cela déclarer le programme et ses paramètres avant, en spécif D, cela s'appelle un PROTOTYPE : DEXEC PR EXTPGM('QCMDEXC') D 250 D 15P 5 CONST **** fin du prototype, déclaration des variables de travail Dcommande S 250 INZ('WRKSPLF') PR indique qu'il s'agit d'un prototype (même positions que DS) EXTPGM le nom du pgm externe CONST sur un paramètre indique que les expressions sont admises C callp exec(commande:%size(commande)) * ou bien ... /free exec(commande:%size(commande)) |
Le même ordre peut être utilisé pour l'appel à des procédures liées (liage par copie[module] ou par référence[programme de service].) il faut alors déclarer la procédure et ses paramètres, avant, en spécif D avec le mot-clé EXTPROC Dinviteclient PR EXTPROC('F4client') D 6 0 D 1 VALUE EXTPROC le nom de la procédure VALUE indique qu'il s'agit d'un paramètre non modifiable, dont on envoi une copie de la valeur,ce qui autorise les expressions, comme avec CONST. (value n'est pas valide avec EXTPGM) ce qui permet C callp inviteclient(nocli:'W')) |
Rappel sur la réception de paramètres : -> la réception des paramètres peut elle même etre réalisée a/ comme avant (*ENTRY PLIST) b/ en spécif D, avec une interface de procédure ( PI ) DProgrammeB PI D nocli 6 0 en entete du programme appelé, pour un programme externe en entete de procédure, dans le cas d'une procédure, comme vu ci-dessous : |
La procèdure peut être dans le même source car RPG-IV admet maintenant plusieurs procédures (au sens ILE) par source. Une procédure ressemble à : - un sous-programme : elle est codée dans le même source elle a des temps de réponse proches elle "voit" les fichiers ouverts par le pgm principal. - à un programme indépendant : elle occupe un niveau d'invocation (influence sur la gestion des erreurs) elle ne connait que ces propres variables. - ni à l'un, ni à l'autre, car : vous choisissez si elle utilisable par un autre pgm. elle peut se présenter sous la forme d'une fonction |
Déclaration d'une procédure ou d'une fonction [OBLIGATOIRE] la délaration se fait par le biais d'un prototype comme vu plus haut. Définition d'une procédure ou d'une fonction Une nouvelle spécif "P" pour définir le début et la fin de la fonction (proche de BEGSR / ENDSR) EXPORT autorise l'utilisation de cette procédure par des modules externes (sinon cette procédure est privée c'est à dire utilisable uniquement dans le même source) Des Spécifs D pour définir les paramètres recus (PI à la place de PR) Et le système VERIFIE que l'interface (PI) est identique au prototype Des Spécifs F, en V6R10, pour définir des fichiers locaux Des Spécifs D pour définir les variables locales Les spécifs C de traitement. |
structure générale d'un pgm RPG-IV : H Spécif H générale |contient NOMAIN s'il n'y a pas de pgm principal F Déclaration de fichiers |(ouvertures globales) D variables globales | D proc1 PR | prototype procédure 1 D proc2 PR | prototype procédure 2 I variables des fichiers | (globales) C traitement | programme principal O sorties | sorties du programme principal P proc1 B -| D PI | définition de l'interface D | variables locales C | traitement P E -| P proc2 B -| D PI | 2ème procédure (idem) D | C | P E -| |
La déclaration du prototype ET de l'interface peut paraitre redondante. il faut analyser cette double déclaration dans les cas (probablement les plus nombreux) ou le programme qui utilise la procédure et la procédure ne sont pas dans le même source les prototypes ammènent alors : + le contrôle du nombre de paramètres et de leur longueur à la COMPIL + la possibilité de passer des paramètres par valeur. le passage de paramètres en RPG se fait naturellement par adresse. - le pgm appelant envoi l'adresse du paramètre - le pgm appelé recoit un pointeur, travail directement sur la mémoire du programme appelant. - au retour le pgm appelant voit sa variable modifiée. ° avec CONST on copie l'information en mémoire temporaire et on envoi l'adresse de cette copie.l'appel peut être un CALLP avec EXTPGM. ° avec VALUE on envoi directement une valeur (une copie), mais le pgm appellé doit une procédure, donc CALLP avec EXTPROC. |
Et tout cela nous ammène vers les fonctions, une fonction est une forme particulière de procédure qui : ° retourne une valeur (la définition est donnée sur les lignes PR ET PI) ° peut donc directement être utilisée en lieu et place de la valeur qu'elle retourne (comme une fonction intégrée %xxx) ° DOIT être déclarée par un prototype (CALL|CALLB sont invalides) Le prototype devant être déclaré aussi bien dans le source écrivant la fonction, que dans tous les sources qui l'utilisent, il est conseillé de placer le prototype dans un source à part et de copier ce source par /COPY fichier,membre On rejoint ansi une philosophie "langage C" ou toutes les fonctions sont externes au langage et ou il faut copier les fichiers de déclaration par les fameux "include stdio.h", etc... |
Exemple: /-- cette fonction retourne du 2 dt 0. / DFindemois PR 2P 0 D D DATFMT(*DMY) P Findemois B [ EXPORT ] * Définition de l'Interface de procédure (PI) * doit être conforme avec le prototype (vérifié à la compilation) D PI 2P 0 D Datein D DATFMT(*DMY) * variables locales D DS D Wdate D DATFMT(*DMY) D wjour 2S 0 OVERLAY(wdate) * traitement C eval wdate = datein C eval wjour = 1 C ADDDUR 1:*M WDATE C SUBDUR 1:*D WDATE C RETURN Wjour P Findemois E |
Récapitulatif. PROTOTYPE : DFINDEMOIS PR 2P 0 D D DATFMT(*DMY/) CONST Sont définis : + le nom du programme/de la procédure (nom externe pouvant être différent) + la définition de la valeur de retour pour une fonction + le type d'appel à réaliser EXTPROC(nom) = Appel d'une procédure->CALLB EXTPGM(nom) = Appel d'un programme ->CALL + le nombre et la nature des paramètres - le nom est facultatif et relève du commentaire - type et longueur - obligatoire (dft) ou optionnel. |
Syntaxe générale : D nom PR lg!type mots-clés Mots-clés admis : DATFMT, DIM, LIKE, PROCPTR, TIMFMT OPDESC demande à ce que le descripteur soit transmis (équivalent à CALLB(D).) la longueur, le type et les mots-clés définissent la valeur retournée. INTERFACE : Pnom-procédure B D PI lg!type mots-clés Sont définis : + la définition de la valeur de retour pour une fonction + le nom, le nombre et la nature des paramètres recus. Mots-clés admis : DATFMT, DIM, LIKE, PROCPTR, TIMFMT, OPDESC |
Définition des paramètres : Spécif D de définition de variable Mots-clés admis : ASCEND, DATFMT, DIM, LIKE, PROCPTR, TIMFMT, (VARYING) v4r20 Nouveaux mots-clés : CONST La valeur est copiée dans une variable temporaire. (conseillé) ==> utilisation possible d'expressions lors de l'appel. VALUE passage d'un paramètre par valeur (et non par adresse) Cette information doit être indiquée aussi bien dans le prototype que dans la procédure utilisée. Il s'agit d'un contrôle réalisé par le compilateur NOOPT pas d'optimisation pour cette variable (OPTIMIZE(*FULL).) |
STATIC cette variable est stockée en mémoire statique: elle est initialisée lors du PREMIER appel, toutes les autres fois elle retrouve sa valeur précédente. les variables globales sont forcément statiques. OPTIONS(*OMIT | *NOPASS | *VARSIZE | *STR) *OMIT la valeur *OMIT (pointeur null) est admise. -> La fonction %ADDR( ) retourne *NULL si le paramètre est omis. *NOPASS le paramètre est facultatif, (les paramètres suivants doivent l'être aussi) -> La fonction %PARMS retourne le nombre de paramètres reçus *VARSIZE paramètre à longueur variable, la longueur indiquée est une longueur maxi, une lg plus petite peu être utilisée Utilisable avec l'API CEEDOD qui décrit les paramètres reçus pour la procédure appelée, mais aussi avec QCMDEXC par exemple. *STR paramètre géré en chaîne compatible C (terminaison x'00') |
ILE va permettre d'utiliser des fonctions écrites ou destinées au C/400. le protypage et les différents mot-clés vont assurer la transposition. correspondance des paramètres ------------------------------ quelques rappels EN C, le passage de paramètres se fait par défaut par valeur EN RPG le passage de paramètres se fait par défaut par référence (on passe un pointeur, comme en C par int*), pour un passage de paramère par valeur, indiquer VALUE EN C, les chaines de caractères sont terminées par x'00', en RPG elles sont à taille fixe, sans terminaison, l'option OPTIONS(*STRING) assure la correspondance, et si la paramètre envoyé est une chaine , GAP stocke l'information en mémoire temporaire, ajoute un zéro héxadécimal et transmet l'adresse (le pointeur). |
+-------------+------------+--------------------------------------------+ + C + RPG 4 + Mots-clés + +-------------+------------+--------------------------------------------+ + int, long + 10I 0 + VALUE + +-------------+------------+--------------------------------------------+ + unsigned int+ 10U 0 + VALUE + +-------------+------------+--------------------------------------------+ + double + 8F 0 + VALUE + +-------------+------------+--------------------------------------------+ + char + 1A + VALUE (il s'agit d'UN octet seul) + +OU ----------+------------+--------------------------------------------+ + char + 10U 0 + VALUE + +-------------+------------+--------------------------------------------+ + short + 10i 0 + VALUE + +-------------+------------+--------------------------------------------+ + int* + 10i 0 + + +-------------+------------+--------------------------------------------+ + unsigned* + 10U 0 + + +-------------+------------+--------------------------------------------+ + double* + 8F 0 + + +-------------+------------+--------------------------------------------+ |
+-------------+------------+--------------------------------------------+ + C + RPG 4 + Mots-clés + +-------------+------------+--------------------------------------------+ + char* + xxxA + OPTIONS(*STRING) + +OU ----------+------------+--------------------------------------------+ + char* + * + VALUE (il faudra utiliser %ADDR().) + +-------------+------------+--------------------------------------------+ + void* + * + VALUE + +(pointeur) + + + +-------------+------------+--------------------------------------------+ + (*) + * + VALUE PROCPTR + +(fonction) + + + +-------------+------------+--------------------------------------------+ L'utilisation du mot-clé CONST sera souvent un plus pour les données élémentaires, par exemple si une fonction C admet un integer, le prototype .................................................................. : D mafonctionC PR extproc('maFonctionC') : : D 10i 0 CONST : :................................................................: permet d'utiliser du décimal paquet, le compilateur assurant la conversion. |
par exemple, la définition suivante double cos(double) se traduit en RPG , par : .................................................................. : D cosinus PR 8F 0 extproc('cos') : : D 8F 0 VALUE : :................................................................: et celle ci (utilisant des chaînes) char* strcpy (char* str1, str2) se traduit en RPG , par : .................................................................. : D stringcopy PR * extproc('strcpy') : : D str1 25A OPTIONS(*STRING) : : D str2 25A OPTIONS(*STRING) : :................................................................: |
Exemple d'un pgm complet utilisant atoi (alpha -> int) et atof (->flot) ----------------------------------------------------------------------- H bnddir('QC2LE') DFTACTGRP(*NO) ACTGRP(*CALLER) D atoi pr 10i 0 extproc('atoi') D num * options(*string) value D atof pr 8f extproc('atof') D num * options(*string) value D i s 10i 0 D p s 13p 7 C movel '-100 ' num 6 C eval i = atoi(%trim(num)) * * I = -100 C eval(h) p = atof(%trim(num)) * * P = -000100.0000000 C movel '-5.67 ' num 6 C eval(h) p = atof(%trim(num)) * * P = -000005.6700000 return |
Pour une valeur retour de type chaine, nous avons deux possibilités : 1/ baser une variable sur le pointeur recu : .................................................................. : D ptr S * : : D chaine S 50A BASED(ptr) : : : : /free : : ptr = stringcopy(chaine1 : chaine2) ; : : if chaine = *blanks; : :................................................................: 2/ Utiliser la fonction RPG %str() .................................................................. : D ptr S * : : D chaine S 50A : : : : /free : : ptr = stringcopy(chaine1 : chaine2) ; : : eval chaine = %str(ptr) : :................................................................: |
Certaines fonctions utilisent des variables globales, par exemple system() H bnddir('QC2LE') DFTACTGRP(*NO) ACTGRP(*CALLER) D Exec pr 10i 0 Extproc('system') D cmd * options(*string) value D ErrMsgID S 7 IMPORT('_EXCP_MSGID') D retour S 10I O /free retour = Exec('DLTSPLF *SELECT'); if retour > 0; if ErrMsgID = 'CPF....' ; .../... /end-free |
tableau des mots-clés et du contexte où ils sont admis : +---------------------+----------------+----------------+----------------| | Mot-clé | Prototype | Procédure | paramètre | | | (PR) | Interface (PI) | (PR ou PI) | +---------------------+----------------+----------------+----------------| | ASCEND | | | A | +---------------------+----------------+----------------+----------------| | CONST | | | A | +---------------------+----------------+----------------+----------------| | DATFMT | A | A | A | +---------------------+----------------+----------------+----------------| | DESCEND | | | A | +---------------------+----------------+----------------+----------------| | DIM | A | A | A | +---------------------+----------------+----------------+----------------| | EXTPGM | A | | | +---------------------+----------------+----------------+----------------| | EXTPROC | A | | | +---------------------+----------------+----------------+----------------| |
+---------------------+----------------+----------------+----------------| | Mot-clé | Prototype | Procédure | paramètre | | | (PR) | Interface (PI) | (PR ou PI) | +---------------------+----------------+----------------+----------------| | LIKE | A | A | A | +---------------------+----------------+----------------+----------------| | NOOPT | | | A | +---------------------+----------------+----------------+----------------| | OPDESC | A | A | | | (pour les API ILE) | | | | +---------------------+----------------+----------------+----------------| | OPTIONS | | | A | +---------------------+----------------+----------------+----------------| | PROCPTR | A | A | A | +---------------------+----------------+----------------+----------------| | TIMFMT | A | A | A | +---------------------+----------------+----------------+----------------| | VALUE | | | A | +------------------------------------------------------------------------+ |