On 2011-03-26, at 2:13 AM, vwf wrote:
> I try to get a Tkx application working with a socket. In Tk you can do
> this with
>
> my $server = IO::Socket::INET->new( LocalPort => 7777,
> Type => SOCK_STREAM, Reuse => 1, Listen => 10 );
> $mw->fileevent($server, 'readable', sub { new_connection($server) });
>
> Can anyone tell me how to do this the Tkx way?
Tkx requires that you use Tkx-based (Tcl) sockets. Something along these lines
(not tested):
my $server = Tkx::socket(-server => [\&accept_connection], 7777);
sub accept_connection {
# may need to shift off magic handle first
my ($sock, $addr, $port) = @_;
Tkx::fconfigure($sock, -blocking => 0);
# Pass in reasonable output, eof and abnormal condition handlers
Tkx::fileevent($sock, readable => [\&fileevent_cmd_handler,
$sock, $output_cmd, $eof_cmd, $abnormal_cmd]);
}
BEGIN {
# Declare $buf outside the function so that we pass the same
# reference to Tcl each time. With a lexical we would create
# new references and new Tcl bindings each time.
my $buf;
sub fileevent_cmd_handler {
my($fh, $output_cmd, $eof_cmd, $abnormal_cmd) = @_;
my $n;
eval { $n = Tkx::gets($fh, \$buf); };
if ($@) {
# call eof_cmd if abnormal_cmd hasn't been specified,
# otherwise just call the abnormal_cmd.
&$eof_cmd($fh) if $eof_cmd && !$abnormal_cmd;
&$abnormal_cmd("$!", $fh) if $abnormal_cmd;
eval { Tkx::close($fh); };
return;
}
if ($n == -1) {
if (Tkx::eof($fh)) {
&$eof_cmd($fh) if $eof_cmd;
eval {Tkx::close($fh);};
&$abnormal_cmd("$!", $fh) if $@ && $abnormal_cmd;
}
return;
}
&$output_cmd($buf, $fh) if $output_cmd;
}
} # BEGIN
The fileevent handler we use ourselves. It's a generic tying function
between Tcl and Perl, and should satisfy most of your needs.
Jeff