Tk::Internals - what is Perl Tk interface doing when you call Tk functions.
This information is worse than useless for "perlTk" users, but can of some help for people interested in using modified Tk source with "perlTk".
This document is under construction. The information is believed to be pertinent to the version of "portableTk" available when it was created. All the details are subject to change.
Before the actual compilation stage a script scans the source and
extracts the subcommands of different commands. This information resides
in the file pTk/Methods.def
.
During compilation the above file is included in the source of
booting routine of dynamic (or static) library. More precisely, the
booting code of module Tk
calls the subroutine
Boot_Glue() from the module tkGlue.c
, and
this subroutine includes the file (with appropriate macro
definitions).
The module bootstraps the C code, then loads the Perl libraries. The
heart of the Perl code is contained in the Tk::Widget
library, all the widgets inherit from this module. Code for toplevels is
loaded from Tk::MainWindow
. During bootstrap of the C glue
code the Xevent::?
codes and a handful of
Tk::Widget
and Tk::Image
routines are defined.
(Much more XSUBs are created from Tk.xs
code.) The widget
subcommands are glued to Perl basing on the list included from
pTk/Methods.def
. In fact all the subcommands are glued to
XSUBs that are related to the same C subroutine
XStoWidget(), but have different data parts. During the
Perl code bootstrap the method Tk::Widget::import
is
called. This call requires all the code from particular widget packages.
Code from the widget packages calls an obscure command like (bless
\"Text")->WidgetClass; This command (actually
Tk::Widget::WidgetClass()) creates three routines:
Tk::Widget::Text(),
Tk::Widget::isText(), and
Tk::Text::isText(). The first one is basically
new
of Tk::Text
, the other two return
constants. It also puts the class into depository.
This is quite intuitive. This call goes direct to
Tk::MainWindow::new
, that calls XSUB
Tk::MainWindow::CreateMainWindow
, that calls C subroutine
Tk_CreateMainWindow(). It is a Tk
subroutine, so here black magic ends (almost). The only remaining black
magic is that the Tk
initialization routine creates a lot
of commands, but the subroutine for creation is usurped by
portableTk and the commands are created in the package
Tk
. They are associated to XSUBs that are related to one of
three C subroutines XStoSubCmd(),
XStoBind(), or XStoTk(), but have
different data parts. The result of the call is blessed into
Tk::MainWindow
, as it should.
The package Tk::Toplevel
defines a lot of subroutines on
the fly on some list. All the commands from the list are converted to
the corresponding subcommands of wm
method of the widget.
Here subcommand is a command with some particular second argument (in
this case "title"
). Recall that the first argument is
$self
. Now Tk::Toplevel
@ISA
Tk::Widget
, that in turn @ISA
Tk
.
So a call to $top->wm(title,Text demo)
calls
Tk::wm
, that is defined during call to
Tk_CreateMainWindow(). As it is described above, the
XSUB associated to XStoSubCmd() is called. This C
routine is defined in tkGlue.c
. It gets the data part of
XSUB, creates a SV
with the name of the command, and calls
Call_Tk() with the XSUB data as the first argument, and
with the name of XSUB stuffed into the Perl stack in the place there
tk
expects it. (In fact it can also reorder the arguments
if it thinks it is what you want). The latter procedure extracts name of
tk
procedure and clientData
from the first
argument and makes a call, using Perl stack as argv
for the
procedure. A lot of black magic is performed afterwards to convert
result of the procedure to a Perl array return.
Above we discussed how the command Tk::Widget::Text
is
created. The above command calls it via inheritance. It is translated to
Tk::Text::new($top, background => $txtBg); The package
Tk::Text
has no method new
, so the
Tk::Widget::new
is called. In turn it calls
Tk::Text->DoInit($top)
, that is
Tk::Widget::DoInit(Tk::Text,$top)
, that initializes the
bindings if necessary. Then it creates the name for the widget of the
form .text0
, and calls
Tk::text(.text0, background => $txtBg)
(note lowercase).
The result of the call is blessed into Tk::Text
, and the
method bindtags
for this object is called. Now the only
thing to discuss is who defines the methods text
and
bindtags
. The answer is that they are defined in
tkWindow.c
, and these commands are created in the package
Tk
in the same sweep that created the command
Tk::wm
discussed above. So the the same C code that
corresponds to the processing of corresponding TCL commands is called
here as well (this time via XStoTk
interface).
As we discussed above, the subcommands of widget procedures
correspond to XSUB XStoWidget
. This XSUB substitutes the
first argument $text
(that is a hash reference) to an
appropriate value from this hash, adds the additional argument after the
first one that contains the name of the subcommand extracted from the
data part of XSUB, and calls the corresponding Tk C subroutine via
Call_Tk
.
Ilya Zakharevich <ilya@math.ohio-state.edu>