调试复杂的CPAN分发时如何定位子程序调用的源文件?

时间:2017-04-05 21:03:19

标签: perl debugging tk

我正在尝试调试Tk程序一段时间。问题似乎是来自顶级窗口的deiconify()调用,但是我无法找到定义deiconify()子的源文件。这是一个简单的例子,只是为了说明我的意思:

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();
}

我首先尝试grep子名 1 的分布:

  • 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 {} \;

然后我尝试在调试器下运行脚本

perl -d test.pl

并在调用$tl->deiconify()之前设置一个断点(见上文)。当我在断点处按s

  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,@_) };

它显示deiconify()被定义为匿名子例程的行(Tk::Submethods的第37行),但是当我再次按s进入匿名子例程时,它只是跳过它返回test.pl中的第32行。

我怀疑该方法必须以某种方式在Tk::wm中定义(因为它与Window管理器有关)可能是通过自动加载机制还是通过dynaloader?

脚注

<子> 1.命令是从Tk发行版的顶层目录运行的。要进行设置,请先运行:

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

1 个答案:

答案 0 :(得分:2)

更自由地对源进行一些更轻松(特别是包括*.c个文件)在文件This procedure is invoked to process the "wm deiconify" Tcl command中找到字符串pTk/mTk/win/tkWinWm.c。这是在介绍C函数WmDeiconifyCmd的注释中,这看起来就像是该功能的实际实现。

我没有打算仔细研究Tk模块XS代码如何将C函数暴露给Perl级别,但如果这是你真正感兴趣的,你现在知道端点,只需要填写中: - )

一旦函数暴露给Perl级别,上面引用的Tk::Submethods中的行显然是注入相应符号表的位置,因此可以通过$tl->deiconify()调用它。