.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "PERLEMBED 1" .TH PERLEMBED 1 "2005-04-10" "DocFr" "User Contributed Perl Documentation" .SH "NOM" .IX Header "NOM" perlembed \- Utiliser Perl dans vos programmes en C ou \*(C+ .SH "DESCRIPTION" .IX Header "DESCRIPTION" .Sh "PRÉAMBULE" .IX Subsection "PRÉAMBULE" Désirez\-vous\ : .IP "\fBUtiliser du C à partir de Perl\ ?\fR" 5 .IX Item "Utiliser du C à partir de Perl?" Consultez perlxstut, perlxs, h2xs, et perlguts. .IP "\fBUtiliser un programme Unix à partir de Perl\ ?\fR" 5 .IX Item "Utiliser un programme Unix à partir de Perl?" Consultez les paragraphes sur les BACK-QUOTES et les fonctions \f(CW\*(C`system\*(C'\fR et \&\f(CW\*(C`exec\*(C'\fR dans perlfunc. .IP "\fBUtiliser du Perl à partir de Perl\ ?\fR" 5 .IX Item "Utiliser du Perl à partir de Perl?" Consultez \*(L"do\*(R" in perlfunc, \*(L"eval\*(R" in perlfunc, \*(L"require\*(R" in perlfunc et \&\*(L"use\*(R" in perlfunc. .IP "\fBUtiliser du C à partir du C\ ?\fR" 5 .IX Item "Utiliser du C à partir du C?" Revoyez votre analyse. .IP "\fBUtiliser du Perl à partir du C\ ?\fR" 5 .IX Item "Utiliser du Perl à partir du C?" Continuez la lecture de ce document... .Sh "\s-1SOMMAIRE\s0" .IX Subsection "SOMMAIRE" .RS 5 \&\*(L"Compiler votre programme C\*(R" .Sp \&\*(L"Ajouter un interpréteur Perl à votre programme C\*(R" .Sp \&\*(L"Appeler un sous-programme Perl à partir de votre programme C\*(R" .Sp \&\*(L"Évaluer un expression Perl à partir de votre programme C\*(R" .Sp \&\*(L"Effectuer des recherches de motifs et des substitutions à partir de votre programme C\*(R" .Sp \&\*(L"Trifouiller la pile Perl à partir de votre programme C\*(R" .Sp \&\*(L"Maintenir un interpréteur persistant\*(R" .Sp \&\*(L"Maintenir de multiples instances d'interpréteur\*(R" .Sp \&\*(L"Utiliser des modules Perl utilisant les bibliothèques C, à partir de votre programme C\*(R" .Sp \&\*(L"Intégrer du Perl sous Win32\*(R" .RE .Sh "Compiler votre programme C" .IX Subsection "Compiler votre programme C" Si vous avez des problèmes pour compiler les scripts de cette documentation, vous n'êtes pas le seul. La règle principale\ : \s-1COMPILER\s0 \s-1LES\s0 \s-1PROGRAMMES\s0 \&\s-1EXACTEMENT\s0 \s-1DE\s0 \s-1LA\s0 MÊME MANIÈRE \s-1QUE\s0 \s-1VOTRE\s0 \s-1PERL\s0 A ÉTÉ COMPILÉ. (désolé de hurler.) .PP De plus, tout programme C utilisant Perl doit être lié à la \fIbibliothèque perl\fR. Qu'est\-ce\ ? Perl est lui\-même écrit en C\ ; la bibliothèque perl est une collection de programmes C qui ont été utilisés pour créer votre exécutable perl (\fI/usr/bin/perl\fR ou équivalent). (Corollaire\ : vous ne pouvez pas utiliser Perl à partir de votre programme C à moins que Perl n'ait été compilé sur votre machine, ou installé proprement \*(-- c'est pourquoi vous ne devez pas copier l'exécutable de Perl de machine en machine sans copier aussi le répertoire \fIlib\fR.) .PP Quand vous utilisez Perl à partir du C, votre programme C \-\-habituellement\*(-- allouera, «\ exécutera\ » et désallouera un objet \fIPerlInterpreter\fR, qui est défini dans la bibliothèque perl. .PP Si votre exemplaire de Perl est suffisamment récent pour contenir ce document (version 5.002 ou plus), alors la bibliothèque perl (et les en\-têtes \fI\s-1EXTERN\s0.h\fR et \fIperl.h\fR, dont vous aurez aussi besoin) résiderons dans un répertoire qui ressemble à\ : .PP .Vb 1 \& /usr/local/lib/perl5/votre_architecture_ici/CORE .Ve .PP ou peut\-être juste .PP .Vb 1 \& /usr/local/lib/perl5/CORE .Ve .PP ou encore quelque chose comme .PP .Vb 1 \& /usr/opt/perl5/CORE .Ve .PP Pour avoir un indice sur l'emplacement de \s-1CORE\s0, vous pouvez exécuter\ : .PP .Vb 1 \& perl -MConfig -e 'print $Config{archlib}' .Ve .PP Voici comment compiler un exemple du prochain paragraphe, \&\*(L"Ajouter un interpréteur Perl à votre programme C\*(R", sur ma machine Linux\ : .PP .Vb 4 \& % gcc -O2 -Dbool=char -DHAS_BOOL -I/usr/local/include \& -I/usr/local/lib/perl5/i586-linux/5.003/CORE \& -L/usr/local/lib/perl5/i586-linux/5.003/CORE \& -o interp interp.c -lperl -lm .Ve .PP (Le tout sur une seule ligne.) Sur ma \s-1DEC\s0 Alpha utilisant une vielle version 5.003_05, l'incantation est un peu différente\ : .PP .Vb 4 \& % cc -O2 -Olimit 2900 -DSTANDARD_C -I/usr/local/include \& -I/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE \& -L/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE -L/usr/local/lib \& -D__LANGUAGE_C__ -D_NO_PROTO -o interp interp.c -lperl -lm .Ve .PP Comment savoir ce qu'il faut ajouter\ ? Dans l'hypothèse où votre Perl est postérieur à la version 5.001, exécutez la commande \f(CW\*(C`perl \-v\*(C'\fR et regardez les valeurs des paramètres \*(L"cc\*(R" et \*(L"ccflags\*(R". .PP Vous aurez à choisir le compilateur approprié (\fIcc\fR, \fIgcc\fR, etc...) pour votre machine\ : \f(CW\*(C`perl \-MConfig \-e 'print $Config{cc}'\*(C'\fR vous indiquera ce qu'il faut utiliser. .PP Vous aurez aussi à choisir le répertoire de bibliothèque approprié(\fI/usr/local/lib/...\fR) pour votre machine. Si votre ordinateur se plaint que certaines fonctions ne sont pas définies, ou qu'il ne peut trouver \&\fI\-lperl\fR, vous devrez alors changer le chemin à l'aide de l'option \&\f(CW\*(C`\-L\*(C'\fR. S'il se plaint qu'il ne peut trouver \fI\s-1EXTERN\s0.h\fR et \fIperl.h\fR, vous devrez alors changer le chemin des en\-têtes à l'aide de l'option \f(CW\*(C`\-I\*(C'\fR. .PP Vous pouvez avoir besoin de bibliothèques supplémentaires. Lesquelles\ ? Peut\-être celles indiquées par .PP .Vb 1 \& perl -MConfig -e 'print $Config{libs}' .Ve .PP Si votre binaire perl est correctement installé et configuré, le module \&\fBExtUtils::Embed\fR pourra déterminer toutes ces informations pour vous\ : .PP .Vb 1 \& % cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP Si le module \fBExtUtils::Embed\fR ne fait pas partie de votre distribution Perl, vous pouvez le récupérer à partir de http://www.perl.com/perl/CPAN/modules/by\-module/ExtUtils::Embed. Si cette documentation est livrée avec votre distribution Perl, c'est que vous utilisez la version 5.004 ou plus et vous l'avez sûrement.) .PP Le kit \fBExtUtils::Embed\fR du \s-1CPAN\s0 contient aussi l'ensemble des sources des exemples de ce document, des tests, des exemples additionnels et d'autres informations qui pourraient vous servir. .Sh "Ajouter un interpréteur Perl à votre programme C" .IX Subsection "Ajouter un interpréteur Perl à votre programme C" Dans un sens perl (le programme C) est un bonne exemple d'intégration de Perl (le langage), donc je vais démontré l'intégration avec \fIminiperlmain.c\fR, inclus dans les sources de la distribution. Voici une version bâtarde, non portable de \fIminiperlmain.c\fR contenant l'essentiel de l'intégration\ : .PP .Vb 2 \& #include /* from the Perl distribution */ \& #include /* from the Perl distribution */ .Ve .PP .Vb 1 \& static PerlInterpreter *my_perl; /*** The Perl interpreter ***/ .Ve .PP .Vb 9 \& int main(int argc, char **argv, char **env) \& { \& my_perl = perl_alloc(); \& perl_construct(my_perl); \& perl_parse(my_perl, NULL, argc, argv, (char **)NULL); \& perl_run(my_perl); \& perl_destruct(my_perl); \& perl_free(my_perl); \& } .Ve .PP Remarquez que nous n'utilisons pas le pointeur \f(CW\*(C`env\*(C'\fR. Normalement passé comme dernier argument de \f(CW\*(C`perl_parse\*(C'\fR, \f(CW\*(C`env\*(C'\fR est remplacé ici par \f(CW\*(C`NULL\*(C'\fR, qui indique que l'environnement courant sera utilisé. .PP Compilons maintenant ce programme (je l'appellerai \fIinterp.c\fR)\ : .PP .Vb 1 \& % cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP Après une compilation réussie, vous pourrez utiliser \fIinterp\fR comme vous le feriez de perl lui\-même\ : .PP .Vb 6 \& % interp \& print "Pretty Good Perl \en"; \& print "10890 - 9801 is ", 10890 - 9801; \& \& Pretty Good Perl \& 10890 - 9801 is 1089 .Ve .PP ou .PP .Vb 2 \& % interp -e 'printf("%x", 3735928559)' \& deadbeef .Ve .PP Vous pouvez aussi lire et exécuter des expressions Perl à partir d'un fichier en plein milieu de votre programme C, en plaçant le nom de fichier dans \&\fIargv[1]\fR avant d'appeler \fIperl_run\fR. .Sh "Appeler un sous-programme Perl à partir de votre programme C" .IX Subsection "Appeler un sous-programme Perl à partir de votre programme C" Pour appeler un sous-programme perl isolé, vous pouvez utiliser les fonctions \&\fIperl_call_*\fR décrite dans perlcall. Dans cet exemple nous allons utiliser \f(CW\*(C`perl_call_argv\*(C'\fR. .PP Ceci est montré ci\-dessous, dans un programme appelé \fIshowtime.c\fR. .PP .Vb 2 \& #include \& #include .Ve .PP .Vb 1 \& static PerlInterpreter *my_perl; .Ve .PP .Vb 5 \& int main(int argc, char **argv, char **env) \& { \& char *args[] = { NULL }; \& my_perl = perl_alloc(); \& perl_construct(my_perl); .Ve .PP .Vb 1 \& perl_parse(my_perl, NULL, argc, argv, NULL); .Ve .PP .Vb 1 \& /*** n'utilise pas perl_run() ***/ .Ve .PP .Vb 1 \& perl_call_argv("showtime", G_DISCARD | G_NOARGS, args); .Ve .PP .Vb 3 \& perl_destruct(my_perl); \& perl_free(my_perl); \& } .Ve .PP où \fIshowtime\fR est un sous-programme qui ne prend aucun argument (c'est le \&\fIG_NOARGS\fR) et dont on ignore la valeur de retour (c'est le G_DISCARD>). Ces drapeaux, et les autres, sont décrits dans perlcall. .PP Je vais définir le sous-programme \fIshowtime\fR dans un fichier appelé \&\fIshowtime.pl\fR\ : .PP .Vb 1 \& print "Je ne devrai pas etre affiche."; .Ve .PP .Vb 3 \& sub showtime { \& print time; \& } .Ve .PP Suffisamment simple. Maintenant compilez et exécutez\ : .PP .Vb 1 \& % cc -o showtime showtime.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP .Vb 2 \& % showtime showtime.pl \& 818284590 .Ve .PP Indique le nombre de secondes écoulées depuis le 1er janvier 1970 (le début de l'ère unix), et le moment où j'ai commencé à écrire cette phrase. .PP Dans ce cas particulier nous n'avons pas besoin d'appeler \fIperl_run\fR, mais en général il est considéré comme étant une bonne pratique de s'assurer de l'initialisation correcte du code de la bibliothèque, incluant l'exécution de toutes les méthodes \f(CW\*(C`DESTROY\*(C'\fR des objets et des blocs \f(CW\*(C`END {}\*(C'\fR des packages. .PP Si vous voulez passer des arguments aux sous-programmes Perl, vous pouvez ajouter des chaînes de caractères à la liste \f(CW\*(C`args\*(C'\fR terminée par \f(CW\*(C`NULL\*(C'\fR passée à \fIperl_call_argv\fR. Pour les autres types de données, ou pour consulter les valeurs de retour, vous devrez manipuler le pile Perl. Ceci est expliqué dans le dernier paragraphe de ce document\ : \*(L"Trifouiller la pile Perl à partir de votre programme C\*(R". .Sh "Évaluer un expression Perl à partir de votre programme C" .IX Subsection "Évaluer un expression Perl à partir de votre programme C" Perl fournit deux fonctions de l'\s-1API\s0 pour évaluer des portions de code Perl. Ce sont \*(L"perl_eval_sv\*(R" in perlguts et \*(L"perl_eval_pv\*(R" in perlguts. .PP Ce sont sans doute les seules fonctions que vous aurez à utiliser pour exécuter des bouts de code Perl à partir de votre programme en C. Votre code peut être aussi long que vous désirez\ ; il peut contenir de nombreuses expressions\ ; il peut utiliser \*(L"use\*(R" in perlfunc, \*(L"require\*(R" in perlfunc, et \&\*(L"do\*(R" in perlfunc d'autres fichiers Perl. .PP \&\fIperl_eval_pv\fR permet d'évalué des expressions Perl, et extraire les variables pour les transformer en types C. Le programme suivant \fIstring.c\fR, exécute trois chaînes Perl, extrait un \f(CW\*(C`int\*(C'\fR de la première, un de la seconde et un \f(CW\*(C`char *\*(C'\fR de la troisième. .PP .Vb 2 \& #include \& #include .Ve .PP .Vb 1 \& static PerlInterpreter *my_perl; .Ve .PP .Vb 3 \& main (int argc, char **argv, char **env) \& { \& char *embedding[] = { "", "-e", "0" }; .Ve .PP .Vb 2 \& my_perl = perl_alloc(); \& perl_construct( my_perl ); .Ve .PP .Vb 2 \& perl_parse(my_perl, NULL, 3, embedding, NULL); \& perl_run(my_perl); .Ve .PP .Vb 3 \& /** Traite $a comme un entier **/ \& perl_eval_pv("$a = 3; $a **= 2", TRUE); \& printf("a = %d\en", SvIV(perl_get_sv("a", FALSE))); .Ve .PP .Vb 3 \& /** Traite $a comme un flottant **/ \& perl_eval_pv("$a = 3.14; $a **= 2", TRUE); \& printf("a = %f\en", SvNV(perl_get_sv("a", FALSE))); .Ve .PP .Vb 3 \& /** Traite $a comme une chaine **/ \& perl_eval_pv("$a = 'rekcaH lreP rehtonA tsuJ'; $a = reverse($a);", TRUE); \& printf("a = %s\en", SvPV(perl_get_sv("a", FALSE), PL_na)); .Ve .PP .Vb 3 \& perl_destruct(my_perl); \& perl_free(my_perl); \& } .Ve .PP Toutes les fonctions étranges comportant \fIsv\fR dans leurs noms aident à convertir les scalaires Perl en types C. Elles sont décrites dans perlguts. .PP Si vous compilez et executez \fIstring.c\fR,vous pourrez voir les résultats de l'utilisation de \fI\fISvIV()\fI\fR pour créer un \f(CW\*(C`int\*(C'\fR, \fI\fISvNV()\fI\fR pour créer un \&\f(CW\*(C`float\*(C'\fR et \fI\fISvPV()\fI\fR pour créer une chaîne\ : .PP .Vb 3 \& a = 9 \& a = 9.859600 \& a = Just Another Perl Hacker .Ve .PP Dans l'exemple ci\-dessus, nous avons créé une variable globale pour stocker temporairement la valeur calculée par nos expressions eval. Il est aussi possible et c'est dans la plupart des cas la meilleur stratégie de récupérer la valeur de retour à partir de \fI\fIperl_eval_pv()\fI\fR à la place. Exemple\ : .PP .Vb 4 \& ... \& SV *val = perl_eval_pv("reverse 'rekcaH lreP rehtonA tsuJ'", TRUE); \& printf("%s\en", SvPV(val,PL_na)); \& ... .Ve .PP De cette manière, nous évitons la pollution de l'espace des noms en ne créant pas de variables globales et nous avons aussi simplifié notre code. .Sh "Effectuer des recherches de motifs et des substitutions à partir de votre programme C" .IX Subsection "Effectuer des recherches de motifs et des substitutions à partir de votre programme C" La fonction \fI\fIperl_eval_sv()\fI\fR nous permet d'évaluer des bouts de code Perl, nous pouvons donc définir quelques fonctions qui l'utilisent pour créer des fonctions «\ spécialisées\ » dans les recherches et substitutions\ : \fI\fImatch()\fI\fR, \fI\fIsubstitute()\fI\fR, et \fI\fImatches()\fI\fR. .PP .Vb 1 \& I32 match(SV *string, char *pattern); .Ve .PP Étant donné une chaîne et un motif (ex., \f(CW\*(C`m/clasp/\*(C'\fR ou \f(CW\*(C`/\eb\ew*\eb/\*(C'\fR, qui peuvent apparaître dans votre programme C comme \*(L"/\e\eb\e\ew*\e\eb/\*(R"), \fImatch()\fR retourne 1 Si la chaîne correspond au motif et 0 autrement. .PP .Vb 1 \& int substitute(SV **string, char *pattern); .Ve .PP Étant donné un pointeur vers un \f(CW\*(C`SV\*(C'\fR et une opération \f(CW\*(C`=~\*(C'\fR (ex., \&\f(CW\*(C`s/bob/robert/g\*(C'\fR ou \f(CW\*(C`tr[A\-Z][a\-z]\*(C'\fR), \fIsubstitute()\fR modifie la chaîne à l'intérieur de l'\f(CW\*(C`AV\*(C'\fR en suivant l'opération, retournant le nombre de substitutions effectuées. .PP .Vb 1 \& int matches(SV *string, char *pattern, AV **matches); .Ve .PP Étant donné un \f(CW\*(C`SV\*(C'\fR, un motif et un pointeur vers un \f(CW\*(C`AV\*(C'\fR vide, \fImatches()\fR évalue \f(CW\*(C`$string =~ $pattern\*(C'\fR dans un contexte de tableau et remplit \&\fImatches\fR avec les éléments du tableau, retournant le nombre de correspondances trouvées. .PP Voici un exemple, \fImatch.c\fR, qui les utilise tous les trois\ : .PP .Vb 2 \& #include \& #include .Ve .PP .Vb 8 \& /** my_perl_eval_sv(code, error_check) \& ** une sorte de perl_eval_sv(), \& ** mais nous retirons la valeur de retour de la pile. \& **/ \& SV* my_perl_eval_sv(SV *sv, I32 croak_on_error) \& { \& dSP; \& SV* retval; .Ve .PP .Vb 2 \& PUSHMARK(SP); \& perl_eval_sv(sv, G_SCALAR); .Ve .PP .Vb 3 \& SPAGAIN; \& retval = POPs; \& PUTBACK; .Ve .PP .Vb 2 \& if (croak_on_error && SvTRUE(ERRSV)) \& croak(SvPVx(ERRSV, PL_na)); .Ve .PP .Vb 2 \& return retval; \& } .Ve .PP .Vb 6 \& /** match(chaine, motif) \& ** \& ** Utilise pour faire des recherches dans un contexte scalaire. \& ** \& ** Retourne 1 si la recherche est reussie; 0 autrement. \& **/ .Ve .PP .Vb 3 \& I32 match(SV *string, char *pattern) \& { \& SV *command = NEWSV(1099, 0), *retval; .Ve .PP .Vb 2 \& sv_setpvf(command, "my $string = '%s'; $string =~ %s", \& SvPV(string,PL_na), pattern); .Ve .PP .Vb 2 \& retval = my_perl_eval_sv(command, TRUE); \& SvREFCNT_dec(command); .Ve .PP .Vb 2 \& return SvIV(retval); \& } .Ve .PP .Vb 7 \& /** substitute(chaine, motif) \& ** \& ** Utilisee pour les operations =~ qui modifient leur membre de gauche (s/// and tr///) \& ** \& ** Retourne le nombre de remplacement effectue \& ** Note: cette fonction modifie la chaine. \& **/ .Ve .PP .Vb 3 \& I32 substitute(SV **string, char *pattern) \& { \& SV *command = NEWSV(1099, 0), *retval; .Ve .PP .Vb 2 \& sv_setpvf(command, "$string = '%s'; ($string =~ %s)", \& SvPV(*string,PL_na), pattern); .Ve .PP .Vb 2 \& retval = my_perl_eval_sv(command, TRUE); \& SvREFCNT_dec(command); .Ve .PP .Vb 3 \& *string = perl_get_sv("string", FALSE); \& return SvIV(retval); \& } .Ve .PP .Vb 7 \& /** matches(chaine, motifs, correspondances) \& ** \& ** Utilise pour faire des recherches dans un contexte tableau. \& ** \& ** Retourne le nombre de correspondance \& ** et remplis le tableau correspondance avec les sous-chaines trouvees. \& **/ .Ve .PP .Vb 4 \& I32 matches(SV *string, char *pattern, AV **match_list) \& { \& SV *command = NEWSV(1099, 0); \& I32 num_matches; .Ve .PP .Vb 2 \& sv_setpvf(command, "my $string = '%s'; @array = ($string =~ %s)", \& SvPV(string,PL_na), pattern); .Ve .PP .Vb 2 \& my_perl_eval_sv(command, TRUE); \& SvREFCNT_dec(command); .Ve .PP .Vb 2 \& *match_list = perl_get_av("array", FALSE); \& num_matches = av_len(*match_list) + 1; /** assume $[ is 0 **/ .Ve .PP .Vb 2 \& return num_matches; \& } .Ve .PP .Vb 7 \& main (int argc, char **argv, char **env) \& { \& PerlInterpreter *my_perl = perl_alloc(); \& char *embedding[] = { "", "-e", "0" }; \& AV *match_list; \& I32 num_matches, i; \& SV *text = NEWSV(1099,0); .Ve .PP .Vb 2 \& perl_construct(my_perl); \& perl_parse(my_perl, NULL, 3, embedding, NULL); .Ve .PP .Vb 1 \& sv_setpv(text, "When he is at a convenience store and the bill comes to some amount like 76 cents, Maynard is aware that there is something he *should* do, something that will enable him to get back a quarter, but he has no idea *what*. He fumbles through his red squeezey changepurse and gives the boy three extra pennies with his dollar, hoping that he might luck into the correct amount. The boy gives him back two of his own pennies and then the big shiny quarter that is his prize. -RICHH"); .Ve .PP .Vb 4 \& if (match(text, "m/quarter/")) /** Does text contain 'quarter'? **/ \& printf("match: Text contains the word 'quarter'.\en\en"); \& else \& printf("match: Text doesn't contain the word 'quarter'.\en\en"); .Ve .PP .Vb 4 \& if (match(text, "m/eighth/")) /** Does text contain 'eighth'? **/ \& printf("match: Text contains the word 'eighth'.\en\en"); \& else \& printf("match: Text doesn't contain the word 'eighth'.\en\en"); .Ve .PP .Vb 3 \& /** Trouve toutes les occurences de /wi../ **/ \& num_matches = matches(text, "m/(wi..)/g", &match_list); \& printf("matches: m/(wi..)/g found %d matches...\en", num_matches); .Ve .PP .Vb 3 \& for (i = 0; i < num_matches; i++) \& printf("match: %s\en", SvPV(*av_fetch(match_list, i, FALSE),PL_na)); \& printf("\en"); .Ve .PP .Vb 7 \& /** Retire toutes les voyelles de text **/ \& num_matches = substitute(&text, "s/[aeiou]//gi"); \& if (num_matches) { \& printf("substitute: s/[aeiou]//gi...%d substitutions made.\en", \& num_matches); \& printf("Now text is: %s\en\en", SvPV(text,PL_na)); \& } .Ve .PP .Vb 4 \& /** Tente une substitution **/ \& if (!substitute(&text, "s/Perl/C/")) { \& printf("substitute: s/Perl/C...No substitution made.\en\en"); \& } .Ve .PP .Vb 5 \& SvREFCNT_dec(text); \& PL_perl_destruct_level = 1; \& perl_destruct(my_perl); \& perl_free(my_perl); \& } .Ve .PP Affiche (les lignes trop longues ont été coupées)\ : .PP .Vb 1 \& match: Text contains the word 'quarter'. .Ve .PP .Vb 1 \& match: Text doesn't contain the word 'eighth'. .Ve .PP .Vb 3 \& matches: m/(wi..)/g found 2 matches... \& match: will \& match: with .Ve .PP .Vb 6 \& substitute: s/[aeiou]//gi...139 substitutions made. \& Now text is: Whn h s t cnvnnc str nd th bll cms t sm mnt lk 76 cnts, \& Mynrd s wr tht thr s smthng h *shld* d, smthng tht wll nbl hm t gt bck \& qrtr, bt h hs n d *wht*. H fmbls thrgh hs rd sqzy chngprs nd gvs th by \& thr xtr pnns wth hs dllr, hpng tht h mght lck nt th crrct mnt. Th by gvs \& hm bck tw f hs wn pnns nd thn th bg shny qrtr tht s hs prz. -RCHH .Ve .PP .Vb 1 \& substitute: s/Perl/C...No substitution made. .Ve .Sh "Trifouiller la pile Perl à partir de votre programme C" .IX Subsection "Trifouiller la pile Perl à partir de votre programme C" Dans la plupart des livres d'informatique, les piles sont expliquées à l'aide de quelque chose comme une pile d'assiettes de cafétéria\ : la dernière chose que vous avez posée sur la pile est la première que vous allez en retirer. Ça correspond à nos buts\ : votre programme C déposera des arguments sur la \*(L"pile Perl\*(R", fermera ses yeux pendant que quelque chose de magique se passe, et retirera le résultat \-\-la valeur de retour de votre sous-programme Perl\*(-- de la pile. .PP Premièrement, vous devez savoir comment convertir les types C en types Perl et inversement, en utilisant \fInewSViv()\fR, \fIsv_setnv()\fR, \fInewAV()\fR et tous leurs amis. Elles sont décrites dans perlguts. .PP Ensuite vous avez besoin de savoir comment manipuler la pile Perl. C'est décrit dans perlcall. .PP Une fois que vous avez compris ceci, intégré du Perl en C est facile. .PP Parce que le C ne dispose pas de fonction prédéfinie pour calculer une puissance entière, rendons l'opérateur Perl ** disponible (ceci est moins utile que ça en a l'air, car Perl implémente l'opérateur ** à l'aide de la fonction C \fI\fIpow()\fI\fR). Premièrement je vais créer une souche de fonction d'exponentiation dans \fIpower.pl\fR\ : .PP .Vb 4 \& sub expo { \& my ($a, $b) = @_; \& return $a ** $b; \& } .Ve .PP Maintenant je vais écrire un programme C, \fIpower.c\fR, avec une fonction \&\fI\fIPerlPower()\fI\fR qui contient tous les perlguts nécessaires pour déposer les deux arguments dans \fI\fIexpo()\fI\fR et récupérer la valeur de retour. Prenez une grande respiration... .PP .Vb 2 \& #include \& #include .Ve .PP .Vb 1 \& static PerlInterpreter *my_perl; .Ve .PP .Vb 18 \& static void \& PerlPower(int a, int b) \& { \& dSP; /* initialise le pointeur de pile */ \& ENTER; /* tout ce qui est cree a partir d'ici */ \& SAVETMPS; /* ... est une variable temporaire */ \& PUSHMARK(SP); /* sauvegarde du pointeur de pile */ \& XPUSHs(sv_2mortal(newSViv(a))); /* depose la base dans la pile */ \& XPUSHs(sv_2mortal(newSViv(b))); /* depose l'exposant dans la pile */ \& PUTBACK; /* rend global le pointeur local de pile */ \& perl_call_pv("expo", G_SCALAR); /* appelle la fonction */ \& SPAGAIN; /* rafraichit le pointeur de pile */ \& /* retire la valeur de retour de la pile */ \& printf ("%d to the %dth power is %d.\en", a, b, POPi); \& PUTBACK; \& FREETMPS; /* libere la valeur de retour */ \& LEAVE; /* ...et retire les arguments empiles */ \& } .Ve .PP .Vb 3 \& int main (int argc, char **argv, char **env) \& { \& char *my_argv[] = { "", "power.pl" }; .Ve .PP .Vb 2 \& my_perl = perl_alloc(); \& perl_construct( my_perl ); .Ve .PP .Vb 2 \& perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL); \& perl_run(my_perl); .Ve .PP .Vb 1 \& PerlPower(3, 4); /*** Calcule 3 ** 4 ***/ .Ve .PP .Vb 3 \& perl_destruct(my_perl); \& perl_free(my_perl); \& } .Ve .PP Compiler et exécuter\ : .PP .Vb 1 \& % cc -o power power.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP .Vb 2 \& % power \& 3 to the 4th power is 81. .Ve .Sh "Maintenir un interpréteur persistant" .IX Subsection "Maintenir un interpréteur persistant" Lorsque l'on développe une application interactive et/ou potentiellement de longue durée, c'est une bonne idée de maintenir un interpréteur persistant plutôt que d'allouer et de construire un nouvel interpréteur de nombreuses fois. La raison principale est la vitesse\ : car Perl ne sera alors chargé qu'une seule fois en mémoire. .PP De toutes façons, vous devez être plus prudent avec l'espace des noms et la portée des variables lorsque vous utilisez un interpréteur persistant. Dans les exemples précédents nous utilisions des variables globales dans le package par défaut \f(CW\*(C`main\*(C'\fR. Nous savions exactement quel code sera exécuté, et supposions que nous pourions éviter les collisions de variables et une extension atroce de la table des symboles. .PP Supposons que notre application est un serveur qui exécutera occasionnellement le code Perl de quelques fichiers arbitraires. Notre serveur n'a plus moyen de savoir quel code il va exécuter. C'est très dangereux. .PP Si le fichier est fourni à \f(CW\*(C`perl_parse()\*(C'\fR, compilé dans un interpréteur nouvellement créé, et subséquemment détruit par \f(CW\*(C`perl_destruct()\*(C'\fR après, vous êtes protégés de la plupart des problèmes d'espace de nom. .PP Une manière d'éviter les collisions d'espace de nom dans ce cas est de transformer le nom de fichier en un nom de package garanti unique, et de compiler le code de ce package en utilisant \*(L"eval\*(R" in perlfunc. Dans l'exemple ci\-dessous, chaque fichier ne sera compilé qu'une seule fois. Ou l'application peut choisir de nettoyer la table des symboles associée au fichier dès qu'il n'est plus nécessaire. En utilisant \*(L"perl_call_argv\*(R" in perlcall, nous allons appeler le sous-programme \f(CW\*(C`Embed::Persistent::eval_file\*(C'\fR contenu dans le fichier \f(CW\*(C`persistent.pl\*(C'\fR et lui passer le nom de fichier et le booléen nettoyer/cacher comme arguments. .PP Notez que le processus continuera de grossir pour chaque fichier qu'il utilisera. De plus, il peut y avoir des sous-programme \f(CW\*(C`AUTOLOAD\*(C'\fR et d'autres conditions qui peuvent faire que la table de symboles Perl grossit. Vous pouvez vouloir ajouter un peu de logique qui surveille la taille du processus, ou qui redémarre tout seul après un certain nombre de requêtes pour être sûr que la consommation mémoire est minimisée. Vous pouvez aussi vouloir limiter la portée de vos variables autant que possible grâce à \*(L"my\*(R" in perlfunc. .PP .Vb 2 \& package Embed::Persistent; \& #persistent.pl .Ve .PP .Vb 3 \& use strict; \& use vars '%Cache'; \& use Symbol qw(delete_package); .Ve .PP .Vb 5 \& sub valid_package_name { \& my($string) = @_; \& $string =~ s/([^A-Za-z0-9\e/])/sprintf("_%2x",unpack("C",$1))/eg; \& # Seconde passe pour les mots commencant par un chiffre. \& $string =~ s|/(\ed)|sprintf("/_%2x",unpack("C",$1))|eg; .Ve .PP .Vb 4 \& # Le transformer en nom de package reel \& $string =~ s|/|::|g; \& return "Embed" . $string; \& } .Ve .PP .Vb 18 \& sub eval_file { \& my($filename, $delete) = @_; \& my $package = valid_package_name($filename); \& my $mtime = -M $filename; \& if(defined $Cache{$package}{mtime} \& && \& $Cache{$package}{mtime} <= $mtime) \& { \& # nous avons deja compile ce sous-programme, \& # il n'a pas ete mis-a-jour sur le disque, rien a faire \& print STDERR "already compiled $package->handler\en"; \& } \& else { \& local *FH; \& open FH, $filename or die "open '$filename' $!"; \& local($/) = undef; \& my $sub = ; \& close FH; .Ve .PP .Vb 8 \& #encadre le code dans un sous-programme de notre package unique \& my $eval = qq{package $package; sub handler { $sub; }}; \& { \& # cacher nos variables dans ce bloc \& my($filename,$mtime,$package,$sub); \& eval $eval; \& } \& die $@ if $@; .Ve .PP .Vb 3 \& # le mettre en cache a moins qu'on le detruit a chaque fois \& $Cache{$package}{mtime} = $mtime unless $delete; \& } .Ve .PP .Vb 2 \& eval {$package->handler;}; \& die $@ if $@; .Ve .PP .Vb 1 \& delete_package($package) if $delete; .Ve .PP .Vb 3 \& #Si vous voulez voir ce qui se passe \& #print Devel::Symdump->rnew($package)->as_string, $/; \& } .Ve .PP .Vb 1 \& 1; .Ve .PP .Vb 1 \& __END__ .Ve .PP .Vb 3 \& /* persistent.c */ \& #include \& #include .Ve .PP .Vb 4 \& /* 1 = Detruire la table des symboles du fichier apres chaque requete, 0 = ne pas le faire */ \& #ifndef DO_CLEAN \& #define DO_CLEAN 0 \& #endif .Ve .PP .Vb 1 \& static PerlInterpreter *perl = NULL; .Ve .PP .Vb 7 \& int \& main(int argc, char **argv, char **env) \& { \& char *embedding[] = { "", "persistent.pl" }; \& char *args[] = { "", DO_CLEAN, NULL }; \& char filename [1024]; \& int exitstatus = 0; .Ve .PP .Vb 5 \& if((perl = perl_alloc()) == NULL) { \& fprintf(stderr, "no memory!"); \& exit(1); \& } \& perl_construct(perl); .Ve .PP .Vb 1 \& exitstatus = perl_parse(perl, NULL, 2, embedding, NULL); .Ve .PP .Vb 2 \& if(!exitstatus) { \& exitstatus = perl_run(perl); .Ve .PP .Vb 1 \& while(printf("Enter file name: ") && gets(filename)) { .Ve .PP .Vb 4 \& /* appeler le sous-programme, passer son nom de fichier en argument */ \& args[0] = filename; \& perl_call_argv("Embed::Persistent::eval_file", \& G_DISCARD | G_EVAL, args); .Ve .PP .Vb 5 \& /* Verifier $@ */ \& if(SvTRUE(ERRSV)) \& fprintf(stderr, "eval error: %s\en", SvPV(ERRSV,PL_na)); \& } \& } .Ve .PP .Vb 5 \& PL_perl_destruct_level = 0; \& perl_destruct(perl); \& perl_free(perl); \& exit(exitstatus); \& } .Ve .PP Compilons\ : .PP .Vb 1 \& % cc -o persistent persistent.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP Voici un exemple de fichier script\ : .PP .Vb 3 \& #test.pl \& my $string = "hello"; \& foo($string); .Ve .PP .Vb 3 \& sub foo { \& print "foo says: @_\en"; \& } .Ve .PP Exécutons\ : .PP .Vb 7 \& % persistent \& Enter file name: test.pl \& foo says: hello \& Enter file name: test.pl \& already compiled Embed::test_2epl->handler \& foo says: hello \& Enter file name: ^C .Ve .Sh "Maintenir de multiples instances d'interpréteur" .IX Subsection "Maintenir de multiples instances d'interpréteur" Quelques rares applications nécessitent de créer plus d'un interpréteur lors d'une session. Une telle application peut décider sporadiquement de libérer toutes les ressources associées à l'interpréteur. .PP Le programme doit s'assurer que ça ait lieu \fIavant\fR qu'un nouvel interpréteur soit construit. Par défaut, la variable globale \f(CW\*(C`PL_perl_destruct_level\*(C'\fR est positionnée à \f(CW0\fR, puisqu'un nettoyage supplémentaire n'est pas nécessaire lorsqu'un programme n'utilise qu'un seul interpréteur. .PP Positionner \f(CW\*(C`PL_perl_destruct_level\*(C'\fR à \f(CW1\fR rend tout plus propre\ : .PP .Vb 1 \& PL_perl_destruct_level = 1; .Ve .PP .Vb 11 \& while(1) { \& ... \& /* repositionner les variables globales avec PL_perl_destruct_level = 1 */ \& perl_construct(my_perl); \& ... \& /* Nettoie et remet a zero _tout_ pendant perl_destruct */ \& perl_destruct(my_perl); \& perl_free(my_perl); \& ... \& /* Recommencons encore et encore ! */ \& } .Ve .PP Lorsque \fI\fIperl_destruct()\fI\fR est appelé, l'arbre d'analyse syntaxique et les tables de symboles de l'interpréteur sont nettoyées, et les variables globales sont repositionnées. .PP Maintenant supposons que nous ayons plus d'une instance d'interpréteur s'exécutant en même temps. Ceci est faisable, mais seulement si le drapeau \&\f(CW\*(C`\-DMULTIPLICITY\*(C'\fR a été utilisé lors de la compilation de Perl. Par défaut, cela positionne \f(CW\*(C`PL_perl_destruct_level\*(C'\fR à \f(CW1\fR. .PP Essayons\ : .PP .Vb 2 \& #include \& #include .Ve .PP .Vb 1 \& /* nous allons integrer deux interpreteurs */ .Ve .PP .Vb 1 \& #define SAY_HELLO "-e", "print qq(Hi, I'm $^X\en)" .Ve .PP .Vb 7 \& int main(int argc, char **argv, char **env) \& { \& PerlInterpreter \& *one_perl = perl_alloc(), \& *two_perl = perl_alloc(); \& char *one_args[] = { "one_perl", SAY_HELLO }; \& char *two_args[] = { "two_perl", SAY_HELLO }; .Ve .PP .Vb 2 \& perl_construct(one_perl); \& perl_construct(two_perl); .Ve .PP .Vb 2 \& perl_parse(one_perl, NULL, 3, one_args, (char **)NULL); \& perl_parse(two_perl, NULL, 3, two_args, (char **)NULL); .Ve .PP .Vb 2 \& perl_run(one_perl); \& perl_run(two_perl); .Ve .PP .Vb 2 \& perl_destruct(one_perl); \& perl_destruct(two_perl); .Ve .PP .Vb 3 \& perl_free(one_perl); \& perl_free(two_perl); \& } .Ve .PP Compilez comme d'habitude\ : .PP .Vb 1 \& % cc -o multiplicity multiplicity.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP Exécutons, exécutons\ : .PP .Vb 3 \& % multiplicity \& Hi, I'm one_perl \& Hi, I'm two_perl .Ve .Sh "Utiliser des modules Perl utilisant les bibliothèques C, à partir de votre programme C" .IX Subsection "Utiliser des modules Perl utilisant les bibliothèques C, à partir de votre programme C" Si vous avez joué avec les exemples ci-dessus et avez essayé d'intégrer un script qui utilise (\fI\fIuse()\fI\fR) un module Perl (tel que \fISocket\fR) qui lui\-même utilise une bibliothèque C ou \*(C+, vous avez probablement vu le message suivant\ : .PP .Vb 3 \& Can't load module Socket, dynamic loading not available in this perl. \& (You may need to build a new perl executable which either supports \& dynamic loading or has the Socket module statically linked into it.) .Ve .PP {Traduction\ : Ne peut charger le module Socket, le chargement dynamique n'est pas disponible dans ce perl. (Vous avez peut\-être besoin de compiler un nouvel exécutable perl qui supporte le chargement dynamique ou qui soit lié statiquement au module Socket.) .PP Quel est le problème\ ? .PP Votre interpréteur ne sait pas communiquer avec ces extensions de son propre chef. Un peu de colle l'aidera. Jusqu'à maintenant vous appeliez \&\fI\fIperl_parse()\fI\fR, en lui passant \s-1NULL\s0 comme second argument\ : .PP .Vb 1 \& perl_parse(my_perl, NULL, argc, my_argv, NULL); .Ve .PP C'est là que le code de collage peut être inséré pour créer le contact initial entre Perl et les routines C/\*(C+ liées. Jettons un coup d'oeil à \fIperlmain.c\fR pour voir comment Perl fait\ : .PP .Vb 5 \& #ifdef __cplusplus \& # define EXTERN_C extern "C" \& #else \& # define EXTERN_C extern \& #endif .Ve .PP .Vb 1 \& static void xs_init _((void)); .Ve .PP .Vb 2 \& EXTERN_C void boot_DynaLoader _((CV* cv)); \& EXTERN_C void boot_Socket _((CV* cv)); .Ve .PP .Vb 8 \& EXTERN_C void \& xs_init() \& { \& char *file = __FILE__; \& /* DynaLoader est un cas special */ \& newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); \& newXS("Socket::bootstrap", boot_Socket, file); \& } .Ve .PP Explication\ : pour chaque extension liée à l'exécutable Perl (déterminé lors de sa configuration initiale sur votre ordinateur ou lors de l'ajout de nouvelles extensions), un sous-programme Perl est créé pour incorporer les routines de l'extension. Normalement, ce sous-programme est nommé \&\fI\fIModule::bootstrap()\fI\fR et est invoqué lors du \fIuse Module\fR. Tour à tour, il passe par un \s-1XSUB\s0, \fIboot_Module\fR, qui créé un pendant pour chaque \s-1XSUB\s0 de l'extension. Ne vous inquiétez pas de cette partie\ ; laissez ceci aux auteurs de \fIxsubpp\fR et des extensions. Si votre extension est chargée dynamiquement, DynaLoader créé au vol \fI\fIModule::bootstrap()\fI\fR pour vous. En fait, si vous disposez d'un DynaLoader fonctionnant correctement, il est rarement nécessaire de lier statiquement d'autres extensions. .PP Une fois que vous disposez de ce code, placez-le en deuxième argument de \&\fI\fIperl_parse()\fI\fR\ : .PP .Vb 1 \& perl_parse(my_perl, xs_init, argc, my_argv, NULL); .Ve .PP Puis compilez\ : .PP .Vb 1 \& % cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts` .Ve .PP .Vb 3 \& % interp \& use Socket; \& use SomeDynamicallyLoadedModule; .Ve .PP .Vb 1 \& print "Maintenant je peux utiliser des extensions!\en"' .Ve .PP \&\fBExtUtils::Embed\fR peut aussi automatiser l'écriture du code de collage \&\fIxs_init\fR. .PP .Vb 4 \& % perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c \& % cc -c perlxsi.c `perl -MExtUtils::Embed -e ccopts` \& % cc -c interp.c `perl -MExtUtils::Embed -e ccopts` \& % cc -o interp perlxsi.o interp.o `perl -MExtUtils::Embed -e ldopts` .Ve .PP Consultez perlxs et perlguts pour plus de détails. .SH "Intégrer du Perl sous Win32" .IX Header "Intégrer du Perl sous Win32" Au moment où j'écris ceci (5.004), il existe deux versions de perl fonctionnant sous Win32. (Ces deux versions fusionnent en 5.005.) S'interfacer avec la bibliothèque Perl d'ActiveState ne se fait pas tout à fait de la même manière que dans les exemples de cette documentation, car de nombreux changements ont été effectués dans l'interface interne de programmation de Perl. Mais il est possible d'intégrer le noyau Perl d'ActiveState. Pour les détails, jetez un oeil à la \s-1FAQ\s0 Perl pour Win32 à http://www.perl.com/perl/faq/win32/Perl_for_Win32_FAQ.html. .PP Avec le Perl \*(L"officiel\*(R" version 5.004 ou plus, tous les exemples de ce document pourront être compilés et exécutés sans modification, même si le processus de compilation est plutôt différent entre Unix et Win32. .PP Pour commencer, les BACKTICKs ne fonctionne pas sous l'interpréteur de commandes natif de Win32. Le kit ExtUtils::Embed du \s-1CPAN\s0 est fourni avec un script appelé \fBgenmake\fR, qui génère un simple makefile pour compiler un programme à partir d'un code source C. Il peut être utilisé de cette manière\ : .PP .Vb 3 \& C:\eExtUtils-Embed\eeg> perl genmake interp.c \& C:\eExtUtils-Embed\eeg> nmake \& C:\eExtUtils-Embed\eeg> interp -e "print qq{I'm embedded in Win32!\en}" .Ve .PP Vous pouvez vouloir utiliser un environnement plus robuste tel que Microsoft Developer Studio. Dans ce cas, exécutez la commande suivante pour générer perlxsi.c\ : .PP .Vb 1 \& perl -MExtUtils::Embed -e xsinit .Ve .PP Créez un nouveau projet et Insérer \-> Fichier dans le projet: perlxsi.c, perl.lib, ainsi que votre propre code source, par ex. interp.c. Typiquement vous pourrez trouver perl.lib dans \fBC:\eperl \&\elib\eCORE\fR, sinon, vous pourrez trouver le répertoire \fB\s-1CORE\s0\fR relatif à \&\f(CW\*(C`perl \-V:archlib\*(C'\fR. Le studio devra aussi connaître ce chemin pour qu'il puisse trouver les fichiers d'en\-têtes Perl. Ce chemin peut être ajouté par le menu Tools \-> Options \-> Directories. Puis sélectionnez Build \-> Build interp.exe et vous pourrez y aller. .SH "MORALITE" .IX Header "MORALITE" Vous pouvez quelquefois \fIécrire du code plus rapide\fR en C, mais vous pourrez toujours \fIécrire plus rapidement du code\fR en Perl. Puisque vous pouvez utiliser l'un avec l'autre, combinez-les comme vous le désirez. .SH "AUTEUR" .IX Header "AUTEUR" Jon Orwant <\fIorwant@tpj.com\fR> and Doug MacEachern <\fIdougm@osf.org\fR>, with small contributions from Tim Bunce, Tom Christiansen, Guy Decoux, Hallvard Furuseth, Dov Grobgeld, and Ilya Zakharevich. .PP Doug MacEachern a écrit un article sur le sujet dans le Volume 1, Issue 4 du The Perl Journal (http://tpj.com). Doug est aussi l'auteur de l'intégration Perl la plus utilisée\ : mod_perl (perl.apache.org), qui intègre Perl au serveur web Apache. Oracle, Binary Evolution, ActiveState, et le nsapi_perl de Ben Sugars ont utilisé ce modèle pour Oracle, Netscape et les extension Perl de Internet Information Server. .PP July 22, 1998 .SH "COPYRIGHT ORIGINAL" .IX Header "COPYRIGHT ORIGINAL" Copyright (C) 1995, 1996, 1997, 1998 Doug MacEachern and Jon Orwant. All Rights Reserved. .PP Permission is granted to make and distribute verbatim copies of this documentation provided the copyright notice and this permission notice are preserved on all copies. .PP Permission is granted to copy and distribute modified versions of this documentation under the conditions for verbatim copying, provided also that they are marked clearly as modified versions, that the authors' names and title are unchanged (though subtitles and additional authors' names may be added), and that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. .PP Permission is granted to copy and distribute translations of this documentation into another language, under the above conditions for modified versions. .SH "TRADUCTION" .IX Header "TRADUCTION" .Sh "Version" .IX Subsection "Version" Cette traduction française correspond à la version anglaise distribuée avec perl 5.005_02. Pour en savoir plus concernant ces traductions, consultez . .Sh "Traducteurs" .IX Subsection "Traducteurs" Marc Carmier <\fIcarmier@immortels.frmug.org\fR> .Sh "Relecture" .IX Subsection "Relecture" Julien Gilles, Gérard Delafond