2017-04-05 1 views
4

J'essaye de déboguer un programme Tk pendant un moment maintenant. Le problème semble être avec un appel deiconify() à partir d'une fenêtre de niveau supérieur, mais je ne suis pas en mesure de localiser le fichier source où le sous deiconify() est défini. Voici un exemple maquillé juste pour illustrer ce que je veux dire:Comment localiser le fichier source d'un appel de sous-programme lors du débogage d'une distribution CPAN complexe?

test.pl:

use strict; 
use warnings; 
use Tk; 

my $mw = MainWindow->new(-title => "Main Window"); 
$mw->Label(-text => "Debugging", -font => "Times 20")->pack(); 
$mw->Button(
    -text => 'Quit', 
    -command => sub { exit }, 
)->pack; 
$mw->Button(
    -text => 'Show window', 
    -command => \&show_window, 
)->pack; 

my $tl = $mw->Toplevel(-title => "Toplevel 1"); 
$tl->Button(
    -text => 'Quit', 
    -command => sub { exit }, 
)->pack; 
$tl->withdraw(); 
MainLoop; 

sub show_window { 
    #$DB::single = 1; 
    $tl->deiconify(); # <--- Where is this sub defined?? 
    $tl->raise(); 
} 

J'ai d'abord essayé de grep la distribution pour le nom sous :

  • find . -name '*.pm' -exec grep -Hn deiconify {} \;
  • find . -name '*.xs' -exec grep -Hn deiconify {} \;
  • find . -name '*.al' -exec grep -Hn deiconify {} \;
  • find . -name '*.h' -exec grep -Hn deiconify {} \;

Alors j'ai essayé d'exécuter le script sous le débogueur

perl -d test.pl 

et mettre un point d'arrêt juste avant l'appel à $tl->deiconify() (voir ci-dessus). Quand je pressais s au point d'arrêt

DB<1> s 
Tk::Submethods::CODE(0x56245540c658)(/home/hakon/perlbrew/perls/perl-5.24.1/lib/site_perl/5.24.1/x86_64-linux/Tk/Submethods.pm:37): 
37:  *{$package.'::'.$sub} = sub { shift->$fn($sub,@_) }; 

il montre la ligne où deiconify() a été définie comme sous-programme anonyme (ligne 37 de Tk::Submethods), mais quand je presse à nouveau s à entrer dans le sous-programme anonyme, il l'étape juste au-dessus et retourne à la ligne 32 en test.pl.

Je suppose que la méthode doit être définie en Tk::wm d'une manière ou d'une autre (puisqu'elle est liée au gestionnaire de fenêtres) peut-être par le mécanisme de chargement automatique ou par dynaloader?

Notes

1. Les commandes a été exécuté à partir du répertoire racine de la distribution Tk. Pour le configurer, exécuter cette première:

cpan -g Tk 
tar zxvf Tk-804.033.tar.gz 
cd Tk-804.033 

+0

Cette ligne est affichée car c'est le code de la méthode 'deiconify': elle est convertie en un appel à la méthode nommée par' $ fn' qui passe '$ sub' (vraisemblablement la chaîne' "deiconify") en tant que premier paramètre. C'est vraisemblablement du code XS si le débogueur ne le montre pas. Qu'est-ce qui est dans '$ fn' à ce moment-là? – Borodin

+0

@Borodin '$ fn' est égal à' wm' autant que je peux voir –

Répondre

2

Grepping la source un peu plus libérale (y compris spécifiquement *.c fichiers) trouve la chaîne This procedure is invoked to process the "wm deiconify" Tcl command dans le fichier pTk/mTk/win/tkWinWm.c. C'est dans un commentaire introduisant la fonction C WmDeiconifyCmd, qui ressemble certainement à l'implémentation réelle de cette fonctionnalité. Je n'ai pas pris la peine de regarder exactement comment le code XS du module Tk expose cette fonction C au niveau Perl, mais si c'est ce qui vous intéresse vraiment, vous connaissez maintenant les points de terminaison et vous n'avez qu'à remplir au milieu :-)

Une fois que la fonction est exposée au niveau Perl, la ligne Tk::Submethods que vous citez ci-dessus est clairement où elle est injectée dans la table de symboles appropriée afin qu'elle puisse être appelée via $tl->deiconify().