internals(3)

NAME

CallingTk - 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 modi
fied 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.

DESCRIPTION

PreCompiling
Before the actual compilation stage a script scans the
source and extracts the subcommands of different com
mands. This information resides in the file "pTk/Meth
ods.def".
Compilation
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).
Inside "use Tk;"
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/Meth
ods.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::Wid
get::import" is called. This call requires all the
code from particular widget packages.
Code from the widget packages calls an obscure command
like

(bless
This command (actually Tk::Widget::WidgetClass()) cre ates three routines: Tk::Widget::Text(), Tk::Wid_ get::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.
Inside "$top = MainWindow->new;"
This is quite intuitive. This call goes direct to
"Tk::MainWindow::new", that calls XSUB
"Tk::MainWindow::CreateMainWindow", that calls C sub
routine Tk_CreateMainWindow(). It is a "Tk" subrou tine, so here black magic ends (almost).
The only remaining black magic is that the "Tk" ini
tialization 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::MainWin
dow", as it should.
Inside "$top->title('Text demo');"
The package "Tk::Toplevel" defines a lot of subrou
tines on the fly on some list. All the commands from
the list are converted to the corresponding subcom
mands 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.
Inside "$text = $top->Text(background => $txtBg);"
Above we discussed how the command "Tk::Widget::Text"
is created. The above command calls it via inheri
tance. 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::Wid
get::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 low
ercase). 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 meth
ods "text" and "bindtags". The answer is that they are
defined in "tkWindow.c", and these commands are cre
ated 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 pro
cessing of corresponding TCL commands is called here
as well (this time via "XStoTk" interface).
Inside "$text->insert('insert','Hello, world!');"
As we discussed above, the subcommands of widget pro
cedures 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>
Copyright © 2010-2025 Platon Technologies, s.r.o.           Index | Man stránky | tLDP | Dokumenty | Utilitky | O projekte
Design by styleshout