我正在尝试调试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
中定义(因为它与窗口管理器有关),可能是通过自动加载机制还是通过dynaloader?脚注
1.这些命令是从Tk发行版的顶级目录运行的。要进行设置,请先运行以下命令:
cpan -g Tk
tar zxvf Tk-804.033.tar.gz
cd Tk-804.033
最佳答案
更加自由地使用源代码(特别是包括*.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()
调用。