Tcl(3pm) | User Contributed Perl Documentation | Tcl(3pm) |
Tcl - Tcl extension module for Perl
use Tcl; $interp = Tcl->new; $interp->Eval('puts "Hello world"');
The Tcl extension module gives access to the Tcl library with functionality and interface similar to the C functions of Tcl. In other words, you can
The Tcl interpreters so created are Perl objects whose destructors delete the interpreters cleanly when appropriate.
The code can come from strings, files or Perl filehandles.
The new procedures can be either C code (with addresses presumably obtained using dl_open and dl_find_symbol) or Perl subroutines (by name, reference or as anonymous subs). The (optional) deleteProc callback in the latter case is another perl subroutine which is called when the command is explicitly deleted by name or else when the destructor for the interpreter object is explicitly or implicitly called.
The variables can be either scalars or hashes.
To create a new Tcl interpreter, use
$interp = Tcl->new;
The following methods and routines can then be used on the Perl object returned (the object argument omitted in each case).
This command returns a new interpreter.
Before invoking procedure PROC special processing is performed on ARG list:
1. All subroutine references within ARG will be substituted with Tcl name which is responsible to invoke this subroutine. This Tcl name will be created using CreateCommand subroutine (see below).
2. All references to scalars will be substituted with names of Tcl variables transformed appropriately.
These first two items allow one to write and expect it to work properly such code as:
my $r = 'aaaa'; button(".d", -textvariable => \$r, -command=>sub {$r++});
3. All references to hashes will be substituted with names of Tcl array variables transformed appropriately.
4. As a special case, there is a mechanism to deal with Tk's special event variables (they are mentioned as '%x', '%y' and so on throughout Tcl). When creating a subroutine reference that uses such variables, you must declare the desired variables using Tcl::Ev as the first argument to the subroutine. Example:
sub textPaste { my ($x,$y,$w) = @_; widget($w)->insert("\@$x,$y", $interp->Eval('selection get')); } $widget->bind('<2>', [\&textPaste, Tcl::Ev('%x', '%y'), $widget] );
This is the lower-level procedure that the 'call' method uses. Arguments are converted efficiently from Perl SVs to Tcl_Objs. A Perl AV array becomes a Tcl_ListObj, an SvIV becomes a Tcl_IntObj, etc. The reverse conversion is done to the result.
Arguments are converted efficiently from Perl SVs to Tcl_Objs. A Perl AV array becomes a Tcl_ListObj, an SvIV becomes a Tcl_IntObj, etc. The reverse conversion is done to the result.
(1) CMDPROC is the address of a C function
(presumably obtained using dl_open and dl_find_symbol. In this case CLIENTDATA and DELETEPROC are taken to be raw data of the ClientData and deleteProc field presumably obtained in a similar way.
(2) CMDPROC is a Perl subroutine
(either a sub name, a sub reference or an anonymous sub). In this case CLIENTDATA can be any perl scalar (e.g. a ref to some other data) and DELETEPROC must be a perl sub too. When CMDNAME is invoked in the Tcl interpreter, the arguments passed to the Perl sub CMDPROC are
(CLIENTDATA, INTERP, LIST)
where INTERP is a Perl object for the Tcl interpreter which called out and LIST is a Perl list of the arguments CMDNAME was called with. If the 1-bit of FLAGS is set then the 3 first arguments on the call to CMDPROC are suppressed. As usual in Tcl, the first element of the list is CMDNAME itself. When CMDNAME is deleted from the interpreter (either explicitly with DeleteCommand or because the destructor for the interpreter object is called), it is passed the single argument CLIENTDATA.
TCLNAME and DESCRNAME get stored in an internal structure, and can be used to purge things fRom the command table via code_destroy or $interp->delete_ref;
Returns (TCLNAME,GENCODE). if you are creating code refs with this you can continue to use the same coderef and it will be converted on each call. but if you save GENCODE, you can replace the anon-coderef call in the tcl command with GENCODE.
for instance
$interp->call('FILEEVENT',$fileref,WRITABLE=>sub {...});
can be replaced by
my ($tclcode,$gencode)=$interp->create_tcl_sub(sub{...}, EVENTS, TCLNAME, DESCRNAME); $interp->call('FILEEVENT',$gencode,WRITABLE=>$gencode);
or
my $sub=sub{....}; $interp->call('FILEEVENT',$fileref,WRITABLE=>$sub);
can be replaced by
my ($tclcode,$gencode)=$interp->create_tcl_sub($sub, EVENTS, TCLNAME, DESCRNAME); $interp->call('FILEEVENT',$gencode,WRITABLE=>$gencode);
although
$interp->call('FILEEVENT',$fileref,WRITABLE=>$sub);
will stil work fine too.
Then you later call
$interp->delete_ref($tclname);
when you are finished with that sub to clean it from the internal tracking and command table. This means no automatic cleanup will occur on the sub{...} or $sub
And after the destroy inside Tcl any triggering writable on
$fileref will fail as well. so it should be
replaced first via
$interp->call('FILEEVENT',$fileref,WRITABLE=>'');
TCLNAME and DESCRNAME get stored in an internal structure, and can be used to purge things form the command table. calling _code_dispose on a TCLNAME retruned from create_tcl_sub removes all use instances and purges the command table. calling _code_dispose on a DESCRNAME passed to create_tcl_sub removes only that instace Code used in a DESCRNAME may be used in other places as well, only when the last usage is purged does the entry get purged from the command table
While the internal tracking structure saves the INTERP the code was added to, it itself does not keep things separated by INTERP, A TCLNAME or DESCRNAMe can only exist in one INTERP at a time, using a new INTERP just causes the one in the last INTERP to disappear, and probably end up with the Tcl code getting deleted
Returns (CODEREF), this is the original coderef
In V1.03 command table cleanup was intoduced. This tries to keep the internal structure and command table clean. In V1.02 and prior heavy use of sub { .. } in Tcl commands could pollute these tables as they were never cleared. Command table cleanup tries to alieviate this.
if you call create_tcl_sub the internal reference exists until you delete_ref or _code_dispose it, or you call create_tcl_sub with the same DESCRNAME.
if the internal reference was created internaly by call(...) there are two rules
the TCLCODES created for that command will be kept at least until a command with the same DESCRNAME and containing a subroutine reference is run again. Since many DESCRNAMES can reference the same TCLNAME only when the last DESCRNAME referencing a TCLNAME is released is the TCLNAME purged.
NOTE: Since
$interp->call('fileevent','sock9827430','writable');
does not contain a subroutine reference, it will not release/free the
TCLNAME/DESCRNAME created by
$interp->call('fileevent','sock9827430','writable',sub{...});
even though that is the way you deactivate a writable/readable callback
in Tcl.
Prior to V1.06 there was also a problem with the coderef never getting cleared from sas, a refcount was kept at the PVCV that prevented it from getting garbage collected, but that SV itself got "lost" and could never be garbage collected, thereby also keeping anything in that codes PAD.
To assist in tracking chages to the internal table and the commands table 3 trace subs were added, set them to non-blank or non-zero to add the tracking output to SYSOUT, like this in your code:
sub Tcl::TRACE_SHOWCODE(){1}
You can tie a Perl variable (scalar or hash) into class Tcl::Var so that changes to a Tcl variable automatically "change" the value of the Perl variable. In fact, as usual with Perl tied variables, its current value is just fetched from the Tcl variable when needed and setting the Perl variable triggers the setting of the Tcl variable.
To tie a Perl scalar $scalar to the Tcl variable tclscalar in interpreter $interp with optional flags $flags (see SetVar above), use
tie $scalar, "Tcl::Var", $interp, "tclscalar", $flags;
Omit the $flags argument if not wanted.
To tie a Perl hash %hash to the Tcl array variable array in interpreter $interp with optional flags $flags (see SetVar above), use
tie %hash, "Tcl::Var", $interp, "array", $flags;
Omit the $flags argument if not wanted. Any alteration to Perl variable $hash{"key"} affects the Tcl variable array(key) and vice versa.
After creation of Tcl interpreter, in addition to evaluation of Tcl/Tk commands within Perl, other way round also instantiated. Within a special namespace " ::perl " following objects are created:
::perl::Eval
So it is possible to use Perl objects from within Tcl.
NOTE: explanations below is for developers managing Tcl/Tk installations itself, users should skip this section.
In order to create Tcl/Tk application with this module, you need to make sure that Tcl/Tk is available within visibility of this module. There are many ways to achieve this, varying on ease of starting things up and providing flexible moveable archived files.
Following list enumerates them, in order of increased possibility to change location.
Install Tcl/Tk first, then install Perl module Tcl, so installed Tcl/Tk will be used. This is most normal approach, and no care of Tcl/Tk distribution is taken on Perl side (this is done on Tcl/Tk side)
Copy installed Tcl/Tk binaries to some location, then install Perl module Tcl with a special action to make Tcl.pm know of this location. This approach makes sure that only chosen Tcl installation is used.
During compiling Tcl Perl module, Tcl/Tk could be statically linked into module's shared library and all other files zipped into a single archive, so each file extracted when needed.
To link Tcl/Tk binaries, prepare their libraries and then instruct Makefile.PL to use these libraries in a link stage. (TODO provide better detailed description)
export_to_tcl takes a hash as arguments, which represents named parameters, with following allowed values:
An example:
use strict; use Tcl; my $int = Tcl->new; $tcl::foo = 'qwerty'; $int->export_to_tcl(subs_from=>'tcl',vars_from=>'tcl'); $int->Eval(<<'EOS'); package require Tk button .b1 -text {a fluffy button} -command perl::fluffy_sub button .b2 -text {a foo button} -command perl::foo entry .e -textvariable perl::foo pack .b1 .b2 .e focus .b2 tkwait window . EOS sub tcl::fluffy_sub { print "Hi, I am a fluffy sub\n"; } sub tcl::foo { print "Hi, I am foo\n"; $tcl::foo++; }
Malcolm Beattie, 23 Oct 1994 Vadim Konovalov, 19 May 2003 Jeff Hobbs, jeff (a) activestate . com, 22 Mar 2004 Gisle Aas, gisle (a) activestate . com, 14 Apr 2004
Special thanks for contributions to Jan Dubois, Slaven Rezic, Paul Cochrane, Huck Finn, Christopher Chavez, SJ Luo.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See http://www.perl.com/perl/misc/Artistic.html
2022-10-20 | perl v5.36.0 |