perlwin32faq8 - Programmation Générale


NOM

perlwin32faq8 - Programmation Générale

Retour en haut de la page


DESCRIPTION

Questions de programmation générale à propos de Perl pour Win32

Comment changer le registre Win32 ?

Plusieurs fonctions de registre Win32 sont fournies par ActivePerl. Consultez le document win32mod accompagnant ActivePerl.

[Voir les docs des modules Win32::TieRegistry et Win32API::Registry -NdT]

Si vous ne comprenez pas comment fonctionne le registre, pensez qu'une clef de registre est un répertoire, une valeur du registre un fichier. Il y a plusieurs clefs de haut niveau, voyez-les comme des disques.

Si vous ne comprenez pas le Registre correctement, il est probablement dans votre intérêt de ne pas y toucher.

Comment lire/écrire sur un pipe de nom ?

Les pipes de noms sont des mécanismes de communications interprocessus, surtout utilisés avec les systèmes Microsoft (comme les plates-formes Win32). Un pipe de nom peut est adressé comme un fichier.

Le nom d'un pipe nommé est un nom UNC (Universal Naming Convention), et ressemble à \\servername\pipe\pipename. servername est le nom du serveur où vous vous connectez, ou pour l'ordinateur courant. pipe est une constante et pipename est le nom du pipe, comme sql pour Microsoft SQL Server.

Vous pouvez utiliser open(), close(), read(), et print() sur un pipe, comme sur un fichier. Cependant, vous ne pouvez utiliser sysread() ou syswrite() car ce ne sont pas réellement des fichiers.

Un programme nommé Win32Pipe se trouve sur l'archive CPAN, il peut être utilisé pour créer des pipes nommés.

Si vous démarrez de zéro, et que vous avez une architecture TCP/IP, considérez l'option d'utiliser des sockets plutôt que des pipes nommés pour vos mécanismes IPC.

Comment écrire des scripts sockets?

Plusieurs exemples de scripts avec des sockets sont distribués avec ActivePerl. Ils sont dans le sous-répertoire eg [eg = exempli gratia en latin = par exemple -NdT] de votre répertoire perl.

Voir Comment écrire un serveur de socket avec ActivePerl ? pour des informations sur les serveurs de sockets.

Que signifie tout ce que j'entends à propos de l'incapacité d'utiliser un socket comme un descripteur de fichier?

Les versions précédentes d'ActivePerl ne permettaient pas de lire ou écrire sur un socket comme si c'était un descripteur de fichier. La version courante supporte pleinement cela, et vous n'avez plus à vous en soucier. Si votre version ne supporte pas cette fonction, récupérez la dernière version d'ActiveState (voir Où est disponible l'interpréteur ActivePerl ?).

Vous n'avez pas à spécifier USE_SOCKETS_AS_FILEHANDLES quand vous construisez ActivePerl pour avoir le fonctionnement des sockets en descripteurs de fichiers. Cela ne gêne pas, mais ce n'est pas nécessaire.

Comment écrire un serveur de socket avec ActivePerl ?

Un exemple de serveurs de sockets, TCP-SERVER, se trouve dans le répertoire eg de votre répertoire perl. En général, les informations pour la programmation de sockets UNIX sont applicables à ActivePerl. Voir tout spécialement la documentation perlipc.

Si vous avez besoin de développer un serveur qui puisse servir plusieurs clients simultanément, regardez le module IO::Select. Ce module vous permet d'écrire un serveur qui gère plusieurs connexions ouvertes par plusieurs clients. Les requêtes individuelles d'une connexion sont placées en file d'attente, donc si votre serveur peut fournir des réponses rapides, cette approche peut très bien fonctionner pour vous. Voici un exemple, adapté de «Programming with Perl Modules» par Erik Olson (un des volumes du Kit de Ressource Perl pour Win32) :

    use IO::Socket;
    use IO::Select;
    # Créer un socket pour écouter.
    #
    my $listener =
      IO::Socket::INET->new( LocalPort => 8008, Listen => 5, Reuse => 1 );
    die "Can't create socket for listening: $!" unless $listener;
    print "Listening for connections on port 8008\n";
    my $readable = IO::Select->new;     # Créer un nouvel objet IO::Select
    $readable->add($listener);          # Ajouter l'écoute
    while(1) {
        # Obtenir la liste des sockets qui veulent parler avec nous.
        #
        my ($ready) = IO::Select->select($readable, undef, undef, undef);
        foreach my $s (@$ready) {
            # Nouvelle connexion ?
            #
            if($s == $listener) {
                # Accepter la connexion et l'ajouter à la liste de lecture.
                #
                my $new_sock = $listener->accept;
                $readable->add($new_sock) if $new_sock;
                print $new_sock "Welcome!\r\n";
            } else {  # It's an established connection
                my $buf = <$s>;   # Try to read a line
                # Quelqu'un à l'autre bout ?
                #
                if( defined $buf ) {
                    # S'il dit au revoir, fermer le socket. Sinon,
                    # afficher ce qu'il dit.
                    #
                    if ($buf =~ /goodbye/i) {
                        print $s "See you later!\n";
                        $readable->remove($s);
                        $s->close;
                    } else {
                        print $s "You said: $buf\n";
                    }
                } else { # Le client est déconnecté.
                    $readable->remove($s);
                    $s->close;
                    print STDERR "Client Connection closed\n";
                }
            }
        }
    }

Pour plus d'information, voir la documentation IO::Socket et IO::Select. Il est aussi possible d'écrire un serveur multi-processus avec ActivePerl, si votre version autorise les threads. Cependant le multitâches est encore un peu expérimental avec Perl 5.005, donc utilisez-le avec précaution. [Avec ActivePerl 5.8.0 les threads sont disponibles en standard contrairement aux versions antérieures où il fallait compiler perl avec une option spéciale. Voir la doc du pragma threads. -NdT]

Comment envoyer ou recevoir des fichiers par FTP ?

Voir le module Net::FTP. Net::FTP est dans le paquetage libnet, disponible sur le CPAN, et peut être installé avec le Gestionnaire de Paquetage Perl (PPM). [libnet est inclus en standard depuis la version 5.6.1 d'ActivePerl -NdT]

Aldo Calpini a développé une extension Win32::Internet pour faire du FTP et HTTP avec la librairie WININET. Voir sa page web à http://dada.perl.it/

Comment envoyer ou recevoir des fichiers par HTTP ?

Le package libwww-perl (LWP) est une collection de modules pour les accès WWW en Perl. LWP est disponible sur le CPAN en source, ou avec le Gestionnaire de Package Perl (PPM). [libwww-perl est inclus en standard depuis la version 5.6.1 d'ActivePerl -NdT]

Aldo Calpini a développé une extension Win32::Internet pour faire du FTP et HTTP avec la librairie WININET. Voir sa page web à http://dada.perl.it/

Comment gérer les comptes utilisateurs avec Perl pour Win32 ?

Une extension nommée Win32::NetAdmin est distribuée avec ActivePerl. L'interface est plutôt de bas niveau, mais il est très possible de gérer les utilisateurs et les groupes avec ce module.

Comment lire/écrire sur des ports série ?

Les ports série peuvent être ouverts comme des fichiers avec ActivePerl. Pour ouvrir COM1, il suffit de faire :

    open( PORT, "+>COM1" ) or die "Impossible d'ouvrir COM1: $!";

Vous devriez pouvoir lire et écrire sur le descripteur de fichier en utilisant les fonctions standards d'Entrée/Sortie (read() et print()), mais pas les fonctions systèmes (sysread() et syswrite()).

Il a été noté (mais pas testé) que les modems utilisant les commandes Hayes demandent un retour chariot (\r) plutôt qu'une fin de ligne (\n) en fin de commande.

[Voir aussi le module Win32-SerialPort -NdT]

Pourquoi l'opérateur -d ne fonctionne-t-il pas ?

En fait, il marche. Cependant, la plupart des gens l'utilisent mal, et obtiennent des résultats erronés. Pour trouver tous les sous répertoires d'un répertoire, essayez :

    $path = shift;
    $path = "." unless $path;
    opendir( DIR, $path )
        or die "Can't open $path: $!";
    while ( $entry = readdir( DIR ) ) {
        $type = ( -d "$path\\$entry" ) ? "dir" : "file"; # $path is crucial!
        print "$type\t$entry\n";
    }
    closedir( DIR );

C'est une erreur fréquente d'ignorer $path dans le test -d. Si vous le faites, perl pense que vous parlez des fichiers du répertoire courant. Comme les répertoires ne sont pas -e dans votre répertoire courant, ils ne sont définitivement pas -d. Exception faite de . et .., qui existent dans tous les répertoires.

Lire où écrire sur des fichiers échoue mystérieusement. Que se passe-t-il ?

Sur les plates-formes Win32, il y a une grande différence entre les fichiers textes et binaires. Pour les fichiers textes, les caractères \r\n sont traduits en \n pendant la lecture depuis le disque, et le caractère ^Z est lu comme le marqueur fin-de-fichier. Pour les fichiers binaires, cette traduction n'est pas utilisée.

Bien que cela fonctionne avec les fichiers textes, cela pose problème quand vous essayez de lire ou d'écrire un fichier binaire. Si la lecture ou l'écriture ne s'arrêtent pas prématurément à cause d'un caractère ^Z, vous aurez la plupart du temps un nombre d'octets incorrects dans le fichier à cause de la traduction \n -> \r\n.

Le problème est que le Perl pour Win32, et la librairie C utilisée, ouvrent le fichiers en mode texte par défaut. Pour chaque descripteur de fichiers que vous utilisez en Perl pour des données binaires, vous devez préciser que ce descripteur est en mode binaire. Heureusement, il y a une fonction, binmode, qui est faite pour ça. Voir binmode pour les détails.

Ce script copie un fichier binaire vers un autre. Notez l'utilisation de binmode pour passer au format binaire.

    open( INFILE, "<$infile" );
    open( OUTFILE, ">$outfile" );
    binmode( INFILE ); binmode( OUTFILE ); # Vital pour les fichiers binaires !
    while ( read( INFILE, $buffer, 1024 ) ) {
        print OUTFILE $buffer;
    }
    close( INFILE );
    close( OUTFILE );

Quand j'essaie d'ouvrir un fichier, j'obtiens une erreur «bad argument».

Les plates-formes Win32 utilisent le caractère '\' comme délimiteur de chemin dans le nom de fichier (C:\comme\ceci). Cependant, le Perl utilise '\' comme code d'échappement, pour symboliser un caractère spécial comme fin de ligne (\n) ou tabulation (\t).

Donc, si vous essayez d'ouvrir un fichier comme ceci :

    open( MYFILE, "C:\temp\newfile.txt" );

vous aurez une erreur. Une solution est de remplacer chaque '\' par un double-'\', pour montrer que vous voulez réellement utiliser ce caractère et pas un échappement :

    open( MYFILE, "C:\\temp\\newfile.txt" );

Une autre solution est d'utiliser un chaîne non interpolée entre simple quote, qui fait savoir à Perl qu'il ne doit pas utiliser de caractères spéciaux :

    open( MYFILE, 'C:\temp\newfile.txt' );

Enfin, vous pouvez aussi utiliser le caractère / pour séparer les composants des répertoires dans les chemins. Vous devez absolument éviter de l'utiliser dans les appels systèmes à des programmes externes, parce que certains programmes ont tendance à traiter / comme un préfixe d'options plutôt qu'en séparateur de répertoire. Toutefois, ActivePerl (et en fait, toutes les API Win32) interprète / comme un séparateur de répertoires, et cela permet un portage plus facile entre UNIX et Win32:

    open( MYFILE, '/temp/newfile.txt' );

Voir la page de documentation perlop pour plus d'informations sur les différences entre simple quote (') et double quotes (``).

Pourquoi ai-je une erreur quand j'utilise la syntaxe perl here-doc (<<), qui dit «Can't find string terminator anywhere before EOF» ?

C'est une erreur étrange qui arrive quand votre terminateur de chaîne de caractères est sur la dernière ligne du script. Avec un script comme :

    print <<"END";
    The snake is old, and his skin is cold. (*)
    END

[(*) «The End» - Jim Morrison -NdT] perl cherche le mot END seul sur une ligne, suivi du caractère fin-de-ligne (\n). Si END est sur la dernière ligne du script, pensez à appuyer sur <Enter> après le mot END, pour que perl l'identifie comme un caractère de terminaison de chaîne.

La plupart des éditeurs textes UNIX le font automatiquement. La plupart des éditeurs Windows ne le font pas. C'est le problème.

Cela peut aussi être dû aux formats Perl, puisqu'ils sont terminés par un . seul sur une ligne. Toutefois, c'est plus rare, puisque les programmeurs spécifient souvent le format de sortie en début de fichier plutôt qu'en fin.

[Voir aussi : Pourquoi est-ce que mes documents <<HERE ne marchent pas ? -NdT]

Retour en haut de la page


AUTEUR ET COPYRIGHT

Cette FAQ a été à l'origine assemblée et maintenue par Evangelo Prodromou. Elle a été révisée et mise à jour par Brian Jepson de O'Reilly and Associates, et David Grove et David Dmytryshyn d'ActiveState.

Cette FAQ est dans le domaine public. Si vous l'utilisez, cependant, vérifiez, s'il vous plaît, que vous donniez le crédit aux auteurs originaux.

Retour en haut de la page


VERSION FRANÇAISE

Cette traduction française correspond à la version anglaise distribuée avec perl 5.8.0. Pour en savoir plus concernant ces traductions, consultez http://www.enstimac.fr/Perl/ .

Retour en haut de la page


TRADUCTION EN FRANÇAIS

Fabien Martinet <ho.fmartinet@cma-cgm.com>

Jean-Louis Morel <jl_morel@bribes.org> (mise à jour perl 5.8.0)

Retour en haut de la page

 perlwin32faq8 - Programmation Générale