POD2-FR
view release on metacpan or search on metacpan
FR/perlxs.pod view on Meta::CPAN
double x
Lorsqu'on utilise des pointeurs C, l'opérateur d'indirection C<*>
devrait être considéré comme une partie du type et l'opérateur
d'addressage C<&> comme une partie de la variable, comme on l'a fait
dans la fonction rpcb_gettime() ci-dessus. Consultez la section sur
les typemaps pour avoir plus de détails sur l'utilisation des
qualificateurs et des opérateurs unaires dans les types C.
Le nom de la fonction et le type de retour doivent être placés sur des
lignes séparées.
INCORRECT CORRECT
double sin(x) double
double x sin(x)
double x
Le corps de la fonction peut être mis en retrait ou ajusté à
gauche. L'exemple suivant montre une fonction dont le corps est ajusté
à gauche. On utilisera un retrait dans la plupart des exemples de ce
document.
CORRECT
double
sin(x)
double
=head2 La pile des arguments
La pile des arguments est utilisée pour stocker les valeurs qui sont
envoyées à la XSUB en tant que paramètres, ainsi que la valeur de
retour de la XSUB. En fait, toutes les fonctions Perl mettent leurs
valeurs sur cette pile en même temps, chacune étant limitée à son
propre intervalle de positions sur la pile. Dans ce document, la
première position dans la pile appartenant à la fonction active sera
désignée comme la position 0 pour cette fonction.
Les XSUB se réfèrent à leurs arguments de la pile avec la macro
B<ST(x)>, où I<x> désigne une position dans l'intervalle appartenant à
la XSUB sur la pile. La position 0 pour cette fonction est connue de
la XSUB comme ST(0). Les paramètres en entrée et les valeurs de retour
de la XSUB commencent toujours à ST(0). Dans de nombreux cas simples,
le compilateur B<xsubpp> générera le code nécessaire à la manipulation
de la pile des arguments en insérant des morceaux de code trouvés dans
les typemaps. Dans les cas plus complexes, le programmeur devra
fournir le code.
=head2 La variable RETVAL
La variable RETVAL est une variable magique qui est toujours du type
retourné par la fonction de la librairie C. Le compilateur B<xsubpp>
fournit cette variable dans chaque XSUB et l'utilise par défaut pour y
mettre la valeur de retour de la fonction C appelée. Dans les cas
simples, la valeur de RETVAL sera mise dans ST(0) sur la pile
d'arguments, où Perl le recevra comme valeur de retour de la XSUB.
Si la XSUB a un type de retour égal à C<void>, le compilateur ne
fournira pas de variable RETVAL pour cette fonction. Lorsqu'on utilise
la directive PPCODE:, la variable RETVAL n'est plus nécessaire, sauf
si on l'utilise explicitement.
Si la directive PPCODE: n'est pas utilisée, la valeur de retour
C<void> devrait être utilisée uniquement pour des sous-routines qui ne
renvoient pas de valeur, I<même si> la directive CODE: est utilisée
pour positionner ST(0) explicitement.
Dans des versions plus anciennes de ce document, on conseillait
d'utiliser la valeur de retour C<void> dans de tels cas. On a
découvert que cela pouvait mener à des segfaults lorsque la XSUB était
I<vraiment> C<void>. Cette pratique est maintenant désapprouvée, et
risque de ne plus être supportée dans une version future. Utilisez la
valeur de retour C<SV *> dans ces cas-là (C<xsubpp> contient
actuellement du code heuristique qui tente de faire la différence
entre les fonctions "vraiment-void" et celles qui sont
"déclarées-void-suivant-l'ancienne-pratique" ; votre code est donc à
la merci de l'heuristique si vous n'utilisez pas C<SV *> comme valeur
de retour).
=head2 Le mot-clé MODULE
Le mot-clé MODULE est utilisé pour marquer le début du code XS et
spécifier un paquetage pour les fonctions que l'on est en train de
définir. Tout le texte qui précède le premier mot-clé MODULE est
considéré comme du code C et sera transféré dans la sortie du
compilateur sans modification. Tout module XS aura une fonction
d'initialisation utilisée pour brancher la XSUB dans Perl. Le nom du
paquetage de cette fonction d'initialisation correspondra à la valeur
de la dernière instruction MODULE dans les fichiers source XS. La
valeur de MODULE devrait toujours rester constante à l'intérieur d'un
même fichier XS, même si cela n'est pas obligatoire.
L'exemple suivant démarre le code XS et place toutes les fonctions
dans un paquetage nommé RPC.
MODULE = RPC
=head2 Le mot-clé PACKAGE
Lorsque les fonctions, à l'intérieur d'un fichier source XS, doivent
être réparties dans des paquetages, il faut utiliser le mot-clé
PACKAGE. Ce mot-clé est utilisé avec le mot-clé MODULE et doit être
spécifié immédiatement après lui.
MODULE = RPC PACKAGE = RPC
[ code XS dans le paquetage RPC ]
MODULE = RPC PACKAGE = RPCB
[ code XS dans le paquetage RPCB ]
MODULE = RPC PACKAGE = RPC
[ code XS dans le paquetage RPC ]
Bien que ce mot-clé soit optionnel et qu'il fournisse des informations
redondantes dans certains cas, il devrait toujours être utilisé. Il
permet de garantir que la XSUB apparaîtra dans le paquetage désiré.
=head2 Le mot-clé PREFIX
Le mot-clé PREFIX désigne des préfixes à supprimer dans les noms de
FR/perlxs.pod view on Meta::CPAN
Dans cet autre exemple, chacun des paramètres en entrée voit son
évaluation retardée.
bool_t
rpcb_gettime(host,timep)
PREINIT:
time_t tt;
INPUT:
char *host
PREINIT:
char *h;
INPUT:
time_t timep
CODE:
h = host;
RETVAL = rpcb_gettime( h, &tt );
timep = tt;
OUTPUT:
timep
RETVAL
=head2 Listes de paramètres de longueur variable
Les XSUB peuvent recevoir des listes de paramètres de longueur
variable en spécifiant une ellipse C<...> dans la liste des
paramètres. Cette utilisation de l'ellipse est similaire à celle que
l'on trouve en C ANSI. Le programmeur peut déterminer le nombre
d'arguments passés à la XSUB en examinant la variable C<items> que le
compilateur B<xsubpp> fournit pour chaque XSUB. Grâce à ce mécanisme,
on peut réaliser une XSUB qui accepte une liste de paramètres de
longueur indéterminée.
Le paramètre I<host> de la XSUB rpcb_gettime() peut être optionnel, de
manière à ce qu'on puisse utiliser l'ellipse pour indiquer que la XSUB
prendra un nombre variable de paramètres. Perl devrait pouvoir appeler
cette XSUB avec chacune des instructions suivantes.
$status = rpcb_gettime( $timep, $host );
$status = rpcb_gettime( $timep );
Voici le code XS, avec l'ellipse :
bool_t
rpcb_gettime(timep, ...)
time_t timep = NO_INIT
PREINIT:
char *host = "localhost";
CODE:
if( items > 1 )
host = (char *)SvPV(ST(1), PL_na);
RETVAL = rpcb_gettime( host, &timep );
OUTPUT:
timep
RETVAL
=head2 Le mot-clé C_ARGS
Le mot-clé C_ARGS permet de réaliser des XSUB que l'on n'appelle pas
de la même manière depuis Perl que depuis C, sans qu'il soit
nécessaire d'écrire une section CODE: ou PPCODE:. Le contenu du
paragraphe C_ARGS est passé comme argument à la fonction C, sans aucun
changement.
Supposons par exemple que la fonction C soit déclarée ainsi :
symbolic nth_derivative(int n, symbolic function, int flags);
et que la valeur par défaut de I<flags> soit contenue dans la variable
C I<default_flags>. Supposons que vous souhaitiez réaliser une
interface que l'on appellera de la manière suivante :
$second_deriv = $function->nth_derivative(2);
Pour cela, déclarez la XSUB ainsi :
symbolic
nth_derivative(function, n)
symbolic function
int n
C_ARGS:
n, function, default_flags
=head2 Le mot-clé PPCODE
Le mot-clé PPCODE: est une variante du mot-clé CODE: qui est utilisée
pour indiquer au compilateur B<xsubpp> que le programmeur fournit le
code contrôlant la pile des arguments pour les valeurs de retour des
XSUB. On souhaite parfois que la XSUB renvoie une liste de valeurs et
non une valeur unique. Dans ce cas-là, il faut utiliser PPCODE: et
rajouter de manière explicite la liste des valeurs sur la pile. Les
mots-clés PPCODE: et CODE: ne sont pas utilisés simultanément dans la
même XSUB.
La XSUB suivante appelle la fonction C rpcb_gettime() et renvoie à Perl
ses deux valeurs de sortie, timep et status, comme une seule liste.
void
rpcb_gettime(host)
char *host
PREINIT:
time_t timep;
bool_t status;
PPCODE:
status = rpcb_gettime( host, &timep );
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newSViv(timep)));
Remarquez que le programmeur doit fournir le code C assurant l'appel
de la vraie fonction rpcb_gettime(), ainsi que le placement correct
des valeurs de retour sur la pile des arguments.
Le type de retour C<void> pour cette fonction indique au compilateur
B<xsubpp> que la variable RETVAL n'est pas nécessaire, qu'elle n'est
pas utlisée, et qu'elle ne devrait pas être créée. Dans la plupart des
cas, il faut utiliser le type de retour void avec l'instruction
PPCODE:.
On utilise la macro EXTEND() afin de dégager de la place sur la pile
des arguments pour les 2 valeurs de retour. L'instruction PPCODE: fait
en sorte que le compilateur B<xsubpp> crée un pointeur vers la pile
dans la variable C<SP> ; c'est ce pointeur qui est utilisé dans la
macro EXTEND(). Les valeurs sont ensuite rajoutées sur la pile avec
les macros PUSHs().
A présent, la fonction rpcb_gettime() peut être utilisée depuis Perl
avec l'instruction suivante.
($status, $timep) = rpcb_gettime("localhost");
Lorsque vous travaillez sur les paramètres en sortie avec une section
PPCODE:, assurez-vous de traiter l'effet 'set'
convenablement. Consultez L<perlguts> pour plus de détails sur cet
effet 'set'.
=head2 Renvoyer undef et des listes vides
Le programmeur voudra parfois renvoyer simplement C<undef> ou une
liste vide si la fonction échoue, plutôt qu'une valeur d'état à
part. La fonction rpcb_gettime() présente justement cette
situation. Nous aimerions que la fonction retourne l'heure si elle
réussit, ou undef si elle échoue. Dans le code Perl suivant, la valeur
de $timep sera soit undef, soit une heure valide;
$timep = rpcb_gettime( "localhost" );
La XSUB suivante n'utilise le type de retour C<SV *> qu'à titre
d'aide-mémoire, et il utilise un bloc CODE: pour indiquer au
compilateur que le programmeur a fourni tout le code
nécessaire. L'appel de sv_newmortal() initialise la valeur de retour à
undef, ce qui en fait la valeur de retour par défaut.
SV *
rpcb_gettime(host)
char * host
PREINIT:
time_t timep;
bool_t x;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) )
sv_setnv( ST(0), (double)timep);
Cet autre exemple montre comment on peut mettre un undef explicite
dans la valeur de retour, au cas où le besoin s'en ferait ressentir.
SV *
rpcb_gettime(host)
char * host
PREINIT:
time_t timep;
bool_t x;
CODE:
ST(0) = sv_newmortal();
if( rpcb_gettime( host, &timep ) ){
sv_setnv( ST(0), (double)timep);
}
else{
ST(0) = &PL_sv_undef;
}
Pour renvoyer une liste vide, il faut utiliser un bloc PPCODE: et ne
pas rajouter de valeur de retour sur la pile.
void
rpcb_gettime(host)
char *host
PREINIT:
time_t timep;
PPCODE:
if( rpcb_gettime( host, &timep ) )
PUSHs(sv_2mortal(newSViv(timep)));
else{
/* Rien n'est remis sur la pile, donc une */
/* liste vide est renvoyee implicitement */
}
Certaines personnes préfèrent rajouter un C<return> explicite dans la
XSUB ci-dessus au lieu de laisser l'exécution se poursuivre jusqu'au
bout. Dans ce cas-là, il convient plutôt d'utiliser C<XSRETURN_EMPTY>,
ce qui garantira que la pile XSUB est ajustée correctement. D'autres
macros sont décrites dans L<perlguts>.
=head2 Le mot-clé REQUIRE
Le mot-clé REQUIRE: sert à indiquer le numéro de version minimal du
compilateur B<xsubpp> requis pour compiler le module XS. Un module XS
contenant l'instruction suivante ne pourra être compilé qu'avec une
version de B<xsubpp> égale ou supérieure à 1.922 :
REQUIRE: 1.922
=head2 Le mot-clé CLEANUP
Ce mot-clé peut être utilisé quand une XSUB doit exécuter des
procédures de nettoyage spéciales avant de se terminer. Quand le
mot-clé CLEANUP: est utilisé, il doit suivre tout bloc CODE:, PPCODE:
ou OUTPUT: présent dans la XSUB. Les instructions spécifiées dans le bloc de
nettoyage seront les dernières instructions de la XSUB.
=head2 Le mot-clé BOOT
Le mot-clé BOOT: permet de rajouter du code dans la fonction
d'amorçage de l'extension. La fonction d'amorçage est générée par le
compilateur B<xsubpp> et contient normalement les instructions
nécessaires pour enregistrer toute XSUB auprès de Perl. Avec le
mot-clé BOOT:, le programmeur peut dire au compilateur de rajouter des
instructions supplémentaires dans la fonction d'amorçage.
Ce mot-clé peut être utilisé n'importe quand après le premier mot-clé
MODULE, et doit être tout seul sur une ligne. La première ligne
blanche après le mot-clé terminera le bloc de code.
BOOT:
# Le message suivant sera affiche lors de l'execution de la
# fonction d'amorcage.
printf("bonjour !\n");
=head2 Le mot-clé VERSIONCHECK
Le mot-clé VERSIONCHECK: correspond aux options C<-versioncheck> et
C<-noversioncheck> de B<xsubpp>. Ce mot-clé prime sur les options de
la ligne de commande. La vérification de version est activée par
défaut. Lorsqu'elle est activée, le module XS essaie de vérifier que
son numéro de version est compatible avec celui du module PM.
Pour activer la vérification de version :
VERSIONCHECK: ENABLE
Pour la désactiver :
VERSIONCHECK: DISABLE
=head2 Le mot-clé PROTOTYPES
Le mot-clé PROTOTYPES: correspond aux options C<-prototypes> et
C<-noprototypes> de B<xsubpp>. Ce mot-clé prime sur les options de la
ligne de commande. Les prototypes sont activés par défaut. Lorsqu'ils
sont activés, les XSUB reçoivent des prototypes Perl. Ce mot-clé peut
être utilisé plusieurs fois dans un module XS pour activer et
désactiver les prototypes dans différentes parties du module.
Pour activer les prototypes :
PROTOTYPES: ENABLE
Pour les désactiver :
PROTOTYPES: DISABLE
=head2 Le mot-clé PROTOTYPE
Ce mot-clé est proche du mot-clé PROTOTYPES: ci-dessus, mais peut être
utilisé pour forcer B<xsubpp> à utiliser un prototype donné pour la
XSUB. Ce mot-clé prime sur toute autre option ou mot-clé relatif au
prototypage, mais n'affecte que la XSUB courante. Consultez
FR/perlxs.pod view on Meta::CPAN
INPUT:
# 'a' est timep, 'b' est host
char *b
time_t a = NO_INIT
CODE:
RETVAL = rpcb_gettime( b, &a );
OUTPUT:
a
RETVAL
CASE:
# 'a' est host, 'b' est timep
char *a
time_t &b = NO_INIT
OUTPUT:
b
RETVAL
Cette fonction peut être appelée avec chacune des instructions
suivantes. Notez la différence dans l'ordre des arguments.
$status = rpcb_gettime( $host, $timep );
$status = x_gettime( $timep, $host );
=head2 L'opérateur unaire &
L'opérateur unaire & est utilisé pour dire au compilateur qu'il doit
déréférencer l'objet lors de l'appel à la fonction C. On utilise ce
procédé lorsqu'on n'a pas mis de bloc CODE: et que l'objet n'est pas
de type pointeur (l'objet est un C<int> ou un C<long>, mais pas un
C<int*> ni un C<long*>).
La XSUB suivante génère du code C incorrect. Le code généré par
B<xsubpp> appellera C<rpcb_gettime()> avec les paramètres C<(char
*host, time_t timep)>, mais le vrai C<rpcb_gettime()> attend un
paramètre C<timep> de type C<time_t *> et non C<time_t>.
bool_t
rpcb_gettime(host,timep)
char *host
time_t timep
OUTPUT:
timep
On résout ce problème en utilisant l'opérateur C<&>. Le compilateur
B<xsubpp>, à présent, traduira la XSUB en code qui appellera
C<rpcb_gettime()> de manière correcte, avec les paramètres C<(char
*host, time_t *timep)>. Il le fait en conservant le C<&> tel quel, de
sorte que l'appel de fonction est C<rpcb_gettime(host, &timep)>.
bool_t
rpcb_gettime(host,timep)
char *host
time_t &timep
OUTPUT:
timep
=head2 Insérer des commentaires et des directives de pré-processeur C
Des directives de pré-processeur C peuvent prendre place à l'intérieur
des blocs BOOT:, PREINIT:, INIT:, CODE:, PPCODE: et CLEANUP:, de même
qu'en dehors des fonctions. Les commentaires sont autorisés partout
après le mot-clé MODULE. Le compilateur transmet les directives de
pré-processeur sans modification et supprime les lignes commentées.
On peut rajouter des commentaires dans les XSUB en mettant un C<#> sur
une ligne comme premier caractère non blanc. Attention, le commentaire
ne doit pas ressembler à une directive de pré-processeur C, sinon il
sera interprété comme tel. Le moyen le plus simple d'éviter cela
consiste à mettre des caractères blancs devant le C<#>.
Si vous utilisez des directives de pré-processeur pour choisir entre
deux versions d'une fonction, utilisez
#if ... version1
#else /* ... version2 */
#endif
et non pas
#if ... version1
#endif
#if ... version2
#endif
car, dans le second cas, xsubpp croira que vous avez défini la
fonction deux fois. Par ailleurs, insérez une ligne blanche avant le
C<#else> et le C<#endif> afin qu'ils ne soient pas considérés comme une
partie intégrante du corps de la fonction.
=head2 Utiliser XS avec C++
Si une fonction est définie comme une méthode C++, alors elle
considère son premier argument comme un pointeur vers un objet. Le
pointeur vers l'objet est stocké dans une variable nommée
THIS. L'objet doit avoir été créé en C++ avec la fonction new(), et il
doit être béni par Perl (comme avec la fonction bless() en Perl pur)
avec la macro sv_setref_pv(). La I<bénédiction> d'un objet par Perl
peut être effectuée par le typemap. Un exemple de typemap est donné à
la fin de cette section.
Si la méthode est définie comme statique, elle appellera la fonction C++
en utilisant la syntaxe classe::methode(). Si la méthode n'est pas
statique, la fonction sera appelée avec la syntaxe THIS-E<gt>method().
Les exemples qui suivent utiliseront la classe C++ que voici :
class color {
public:
color();
~color();
int blue();
void set_blue( int );
private:
int c_blue;
};
Les XSUB pour les méthodes blue() et set_blue() sont définies avec le
nom de la classe, mais le paramètre pour l'objet (THIS, ou "self") est
implicite et il n'est pas mentionné dans la liste.
( run in 1.753 second using v1.01-cache-2.11-cpan-5511b514fd6 )