Probleme d'appel de fonctions dans des modules 'Objets'
2 réponses
schirrms
Bonjour,
C'est mon premier post sur ce groupe, donc, rapide pr=E9sentation :
Je ne suis pas d=E9veloppeur, mais en tant qu'administrateur de r=E9seaux
et syst=E8mes, j'ai d=E9j=E0 un certain nombre de scripts (en shell, awk,
bat et perl) qui tournent.
Ces deux derni=E8res ann=E9es, je n'ai quasi plus qu'=E9crit en perl, ce qu=
i
ne fait pas de moi une r=E9f=E9rence de ce language :-)
Je vous sollicite pour le point suivant :
j'ai =E9crit deux librairies 'orient=E9es objet', une qui me sert =E0 g=E9r=
er
mes logs, une autre qui me fournit des fonctions de gestion d'un
serveur DNS. Ces deux librairies semblent fonctionner comme je le
souhaite.
J'initie la premi=E8re en faisant un
my $logit =3D MiscPS!!Log_It->new( parametres de log en fonctions de mes
besoins)
et la seconde en faisant
my $DnsCmd=3DWin32::dnscmd->new(parametres de connexion au serveur DNS,
et autres en fonctions de mes besoins).
Jusque l=E0, tout va bien.
Dans mon programme principal, je fais parfois appel =E0 une fonction de
log en fonction du niveau de debug que j'ai mis en place. Cette
fonction est dans la librarie LogIT, je l'appelle ainsi :
$logit->debuglog(5, "$ph-$annu{ $ph }\n" );
Je souhaiterais permettre =E0 ma libraire dnscmd d'utiliser la fonction
debuglog, mais de la mani=E8re la plus 'l=E2che' possible. En d'autres
termes, je ne souhaites pas que dnscmd soit oblig=E9e de faire un appel
direct =E0 logit, mais je voudrais au contraire que le programme
principal passe une r=E9f=E9rence =E0 cette fonction =E0 dnscmd.
Ainsi, vu de la librarie dnscmd, si la r=E9f=E9rence a =E9t=E9 pass=E9e, le=
s
messages de d=E9bug sont pass=E9s =E0 cette fonction, sinon dnscmd affiche
les messages de d=E9bug sur la sortie standard (ou stderr, l=E0 n'est pas
le probl=E8me).
Ouf ! quel long post !
1) Me 'fourvoi-je' compl=E8tement ? Ma d=E9marche est-elle incoh=E9rente ?
2) Si je ne suis pas dans le gaz, comment passer une r=E9f=E9rence ? Je
suis arriv=E9 =E0 passer une r=E9f=E9rence =E0 la variable '$logit', et don=
c,
depuis la librarie dnscmd, j'arrive =E0 faire $$pouetpouet->log, mais ce
n'est pas vraiment 'ind=E9pendant comme processus !
1) Me 'fourvoi-je' complètement ? Ma démarche est-elle incohérente ?
Oui et non... Ça dépend du point de vue.
2) Si je ne suis pas dans le gaz, comment passer une référence ? Je suis arrivé à passer une référence à la variable '$logit', et donc, depuis la librarie dnscmd, j'arrive à faire $$pouetpouet->log, mais ce n'est pas vraiment 'indépendant comme processus !
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On passe un objet en supposant qu'il a une méthode 'log'. On peut "améliorer" la chose en passant en plus le nom de la méthode à appeller ('log' peut-être remplacé par le nom d'une variable). Au passage, pourquoi passer une référence à $logit : c'est un objet et donc c'est déjà une référence !
2- Deuxième manière objet : définir une classe implémentant l'interface de log attendue par les objets de la classe DNS. Définir une instance par défaut qui fait un 'log' sur stderr par exemple. Et enrober $logit dans une autre instance de cette classe pour qu'il puisse remplacer l'instance par défaut.
3- Une manière par fermeture (closure) : définir une fermeture qui cache l'objet $logit et l'appel à 'log' et passer cette subroutine anonyme comme callback à dnscmd :
$dnscmd->install_callback_log( sub { # on peut ajouter des paramètres fixes (ici 5) $logit->log(5, @_); } );
(la méthode 'install_callback_log' stocke la sub anonyme dans un des attributs de l'objet $dnscmd. Posons que cet attribut s'appelle 'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message"; if (defined $dnscmd->cblog) { $dnscmd->cblog->($mes); } else { print STDERR "$mesn"; }
1) Me 'fourvoi-je' complètement ? Ma démarche est-elle incohérente ?
Oui et non... Ça dépend du point de vue.
2) Si je ne suis pas dans le gaz, comment passer une référence ? Je
suis arrivé à passer une référence à la variable '$logit', et donc,
depuis la librarie dnscmd, j'arrive à faire $$pouetpouet->log, mais ce
n'est pas vraiment 'indépendant comme processus !
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins
trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On
passe un objet en supposant qu'il a une méthode 'log'. On peut
"améliorer" la chose en passant en plus le nom de la méthode à
appeller ('log' peut-être remplacé par le nom d'une variable). Au
passage, pourquoi passer une référence à $logit : c'est un objet et
donc c'est déjà une référence !
2- Deuxième manière objet : définir une classe implémentant
l'interface de log attendue par les objets de la classe DNS. Définir
une instance par défaut qui fait un 'log' sur stderr par exemple. Et
enrober $logit dans une autre instance de cette classe pour qu'il
puisse remplacer l'instance par défaut.
3- Une manière par fermeture (closure) : définir une fermeture qui
cache l'objet $logit et l'appel à 'log' et passer cette subroutine
anonyme comme callback à dnscmd :
$dnscmd->install_callback_log(
sub {
# on peut ajouter des paramètres fixes (ici 5)
$logit->log(5, @_);
}
);
(la méthode 'install_callback_log' stocke la sub anonyme dans un des
attributs de l'objet $dnscmd. Posons que cet attribut s'appelle
'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message";
if (defined $dnscmd->cblog) {
$dnscmd->cblog->($mes);
} else {
print STDERR "$mesn";
}
--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
1) Me 'fourvoi-je' complètement ? Ma démarche est-elle incohérente ?
Oui et non... Ça dépend du point de vue.
2) Si je ne suis pas dans le gaz, comment passer une référence ? Je suis arrivé à passer une référence à la variable '$logit', et donc, depuis la librarie dnscmd, j'arrive à faire $$pouetpouet->log, mais ce n'est pas vraiment 'indépendant comme processus !
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On passe un objet en supposant qu'il a une méthode 'log'. On peut "améliorer" la chose en passant en plus le nom de la méthode à appeller ('log' peut-être remplacé par le nom d'une variable). Au passage, pourquoi passer une référence à $logit : c'est un objet et donc c'est déjà une référence !
2- Deuxième manière objet : définir une classe implémentant l'interface de log attendue par les objets de la classe DNS. Définir une instance par défaut qui fait un 'log' sur stderr par exemple. Et enrober $logit dans une autre instance de cette classe pour qu'il puisse remplacer l'instance par défaut.
3- Une manière par fermeture (closure) : définir une fermeture qui cache l'objet $logit et l'appel à 'log' et passer cette subroutine anonyme comme callback à dnscmd :
$dnscmd->install_callback_log( sub { # on peut ajouter des paramètres fixes (ici 5) $logit->log(5, @_); } );
(la méthode 'install_callback_log' stocke la sub anonyme dans un des attributs de l'objet $dnscmd. Posons que cet attribut s'appelle 'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message"; if (defined $dnscmd->cblog) { $dnscmd->cblog->($mes); } else { print STDERR "$mesn"; }
On 9 sep, 11:35, Paul Gaborit wrote: Merci, merci beaucoup pour ces réponses ! Il m'a fallu un peu de temps pour pouvoir les exploiter!
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On passe un objet en supposant qu'il a une méthode 'log'. On peut "améliorer" la chose en passant en plus le nom de la méthode à appeller ('log' peut-être remplacé par le nom d'une variable). Au passage, pourquoi passer une référence à $logit : c'est un objet et donc c'est déjà une référence !
C'est en fait ce que je cherchais à faire. Vous m'avez donné les clef qui me manquaient, et maintenant çà fonctionne. Simplement, je restais bloqué sur un point que je n'avais pas détecté : En fait, dans la fonction new de mon dnscmd j'avais mis : $self->{logobject} = $_[0]; $self->{logfunct} = $_[1];
Et dans ma fonction _debug, j'avais mis ceci : $self->{logobject}->$self->{logfunct}(4, "Bonjour de test2b-
tolog");
Ceci ne fonctionne pas, car je ne dois pas savoir comment 'protéger la 'variable' $self->{logfunct}. Ce qui fonctionne, c'est ceci : my $funct = $self->{logfunct}; $self->{logobject}->$funct(4, "Bonjour de test2b->tolog");
Je suppose qu'il existe une version plus élégante :-)
2- Deuxième manière objet : définir une classe implémentant l'interface de log attendue par les objets de la classe DNS. Définir une instance par défaut qui fait un 'log' sur stderr par exemple. Et enrober $logit dans une autre instance de cette classe pour qu'il puisse remplacer l'instance par défaut.
Là, j'avoue que çà dépasse mes compétences de compréhension. Si vous avez quelques minutes à perdre pour détailler, ce sera pour ma culture générale, sinon, ce n'est pas important.
3- Une manière par fermeture (closure) : définir une fermeture qui cache l'objet $logit et l'appel à 'log' et passer cette subroutine anonyme comme callback à dnscmd :
$dnscmd->install_callback_log( sub { # on peut ajouter des paramètres fixes (ici 5) $logit->log(5, @_); } );
(la méthode 'install_callback_log' stocke la sub anonyme dans un des attributs de l'objet $dnscmd. Posons que cet attribut s'appelle 'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message"; if (defined $dnscmd->cblog) { $dnscmd->cblog->($mes); } else { print STDERR "$mesn"; }
Ce mode là, je ne l'avais pas du tout imaginé, mais je l'ai testé, il fonctionne parfaitement, magnifique (je reste un grand enfant face à Perl :-)
Je vous remercie encore !
Pascal
On 9 sep, 11:35, Paul Gaborit <Paul.Gabo...@invalid.invalid> wrote:
Merci, merci beaucoup pour ces réponses ! Il m'a fallu un peu de temps
pour pouvoir les exploiter!
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins
trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On
passe un objet en supposant qu'il a une méthode 'log'. On peut
"améliorer" la chose en passant en plus le nom de la méthode à
appeller ('log' peut-être remplacé par le nom d'une variable). Au
passage, pourquoi passer une référence à $logit : c'est un objet et
donc c'est déjà une référence !
C'est en fait ce que je cherchais à faire. Vous m'avez donné les clef
qui me manquaient, et maintenant çà fonctionne.
Simplement, je restais bloqué sur un point que je n'avais pas
détecté :
En fait, dans la fonction new de mon dnscmd j'avais mis :
$self->{logobject} = $_[0];
$self->{logfunct} = $_[1];
Et dans ma fonction _debug, j'avais mis ceci :
$self->{logobject}->$self->{logfunct}(4, "Bonjour de test2b-
tolog");
Ceci ne fonctionne pas, car je ne dois pas savoir comment 'protéger la
'variable' $self->{logfunct}.
Ce qui fonctionne, c'est ceci :
my $funct = $self->{logfunct};
$self->{logobject}->$funct(4, "Bonjour de test2b->tolog");
Je suppose qu'il existe une version plus élégante :-)
2- Deuxième manière objet : définir une classe implémentant
l'interface de log attendue par les objets de la classe DNS. Définir
une instance par défaut qui fait un 'log' sur stderr par exemple. Et
enrober $logit dans une autre instance de cette classe pour qu'il
puisse remplacer l'instance par défaut.
Là, j'avoue que çà dépasse mes compétences de compréhension. Si vous
avez quelques minutes à perdre pour détailler, ce sera pour ma culture
générale, sinon, ce n'est pas important.
3- Une manière par fermeture (closure) : définir une fermeture qui
cache l'objet $logit et l'appel à 'log' et passer cette subroutine
anonyme comme callback à dnscmd :
$dnscmd->install_callback_log(
sub {
# on peut ajouter des paramètres fixes (ici 5)
$logit->log(5, @_);
}
);
(la méthode 'install_callback_log' stocke la sub anonyme dans un des
attributs de l'objet $dnscmd. Posons que cet attribut s'appelle
'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message";
if (defined $dnscmd->cblog) {
$dnscmd->cblog->($mes);
} else {
print STDERR "$mesn";
}
Ce mode là, je ne l'avais pas du tout imaginé, mais je l'ai testé, il
fonctionne parfaitement, magnifique (je reste un grand enfant face à
Perl :-)
On 9 sep, 11:35, Paul Gaborit wrote: Merci, merci beaucoup pour ces réponses ! Il m'a fallu un peu de temps pour pouvoir les exploiter!
Il y a plusieurs moyens de répondre à votre besoin. En voici au moins trois.
1- Une manière objet : celle que vous avez adoptée (ou presque). On passe un objet en supposant qu'il a une méthode 'log'. On peut "améliorer" la chose en passant en plus le nom de la méthode à appeller ('log' peut-être remplacé par le nom d'une variable). Au passage, pourquoi passer une référence à $logit : c'est un objet et donc c'est déjà une référence !
C'est en fait ce que je cherchais à faire. Vous m'avez donné les clef qui me manquaient, et maintenant çà fonctionne. Simplement, je restais bloqué sur un point que je n'avais pas détecté : En fait, dans la fonction new de mon dnscmd j'avais mis : $self->{logobject} = $_[0]; $self->{logfunct} = $_[1];
Et dans ma fonction _debug, j'avais mis ceci : $self->{logobject}->$self->{logfunct}(4, "Bonjour de test2b-
tolog");
Ceci ne fonctionne pas, car je ne dois pas savoir comment 'protéger la 'variable' $self->{logfunct}. Ce qui fonctionne, c'est ceci : my $funct = $self->{logfunct}; $self->{logobject}->$funct(4, "Bonjour de test2b->tolog");
Je suppose qu'il existe une version plus élégante :-)
2- Deuxième manière objet : définir une classe implémentant l'interface de log attendue par les objets de la classe DNS. Définir une instance par défaut qui fait un 'log' sur stderr par exemple. Et enrober $logit dans une autre instance de cette classe pour qu'il puisse remplacer l'instance par défaut.
Là, j'avoue que çà dépasse mes compétences de compréhension. Si vous avez quelques minutes à perdre pour détailler, ce sera pour ma culture générale, sinon, ce n'est pas important.
3- Une manière par fermeture (closure) : définir une fermeture qui cache l'objet $logit et l'appel à 'log' et passer cette subroutine anonyme comme callback à dnscmd :
$dnscmd->install_callback_log( sub { # on peut ajouter des paramètres fixes (ici 5) $logit->log(5, @_); } );
(la méthode 'install_callback_log' stocke la sub anonyme dans un des attributs de l'objet $dnscmd. Posons que cet attribut s'appelle 'cblog'.)
Ensuite pour l'utiliser :
my $mes = "un message"; if (defined $dnscmd->cblog) { $dnscmd->cblog->($mes); } else { print STDERR "$mesn"; }
Ce mode là, je ne l'avais pas du tout imaginé, mais je l'ai testé, il fonctionne parfaitement, magnifique (je reste un grand enfant face à Perl :-)