in reply to Missing base classes when called from Tk

so the routines are called like
They are not. \&subroutine (or Foo::subroutine) is not Foo->subroutine
  • Comment on Re: Missing base classes when called from Tk

Replies are listed 'Best First'.
Re^2: Missing base classes when called from Tk
by perl-diddler (Chaplain) on Sep 27, 2007 at 11:34 UTC
    This may be an area of confusion for me.

    When I said "the routines are called like"...I meant my "key handler routine" is called by Tk with a calling sequence that looks like: "$main_win->handle_key($s, Ev('A'), Ev('K'))", where "$s" is the main "self" data structure/pointer."

    i.e. The bind for my "handle_key" routine is:

    { use Tk; #needed for "Ev" defines next code line $retval = $main_win -> bind('<Any-KeyPress>' => [\&handle_key, $s, Ev('A'), Ev('K')]); }
    From the man page on Tk::callbacks, I see:
    Another use of arguments allows you to write generalized method +s which are easier to re-use: $a->bind("<Next>",['Next','Page']); $a->bind("<Down>",['Next','Line']); This will call $a->Next('Page') or $a->Next('Line') respectivel +y.
    From my call sequence:
    "$main_win" -> bind('<Any-KeyPress>', \&handle_key, $s, Ev('A'), Ev('K'));"
    I'd expect "handle_key" to be entered with the following in '@_':
    my ($main_win, $s, $EvA, $EvK) = @_;
    I assume "$main_win (handle of win I'm binding to) to be first, and the other 3 args should taken from my bind statement.

    I pass the key_handler routine addr to Tk via the bind, but it is from the man pages I get that they are calling &handle_key as being called through the "$main_win" handle. I pass my 1 object (at top level is a singleton, I believe the terminology is) -- that contains the "database" I'm sequencing through. The routine that has the bind statement in it, is passed "$s" ($self), which it passes in a param list to &handle_key. I then try to invoke methods on the "$self" object that is passed in via the parameter list. It is some of those "methods" that the "call" should find in Base classes but isn't (doesn't seem to be searching through the base classes at all).

    Did that clarify anything or where I might be using it incorrectly?
    Sorry for any confusion....
    L

      Tk callbacks don't respect use -> (or @ISA )
        Yeah...I think I understand that...but shouldn't "jump tables" defined within a package that access (use) ancestor functions use @ISA?

        None of my "("two or one, since timer is currently 'disabled'")" Tk event handler routines rely on searching @ISA. The handler is in the same "class" (package) as the "bind" statement that is 'binding' it to Tk. As for associating the method's invocation with the correct instance, I only allow 1 instance of an "open database" per program. So any methods called by Tk refer to the 1 program-wide instance (any wonder why global variables in the none OO were so useful?... but also, so constraining).

        The key handler makes an indirect call (or two). The entire code snipplet (which I plan on simplifying, later, once I get it "working" again -- I started from the linear, working 'proof-of-concept' code that was my first "version" of this program, but bound to '<Any_Keypress>', is this routine:

        sub __handle_key { my ( $s, $key_event, $key_code) = @_[1..3]; my $image_win = $s->image_win; # use Readonly; Readonly my $single_key_commands => "\003\015\033 +-0123456789 +RWbnpq"; Readonly my @single_key_functions => ( \&_abort, \&next_rand_or_recorded_entry, \&_abort, \&_space, \&inc_cur_rating, \&dec_cur_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_set_rating, \&_reset_to_beginning_entry, \&write_db, \&backup_entry, \&next_rand_or_recorded_entry, + \&_pause, \&_quit ); Readonly my @key_code_commands => qw( Left Up Right Down Home +KP_Home); Readonly my @key_code_functions => ( \&backup_entry,\&backup_entry, \&next_rand_or_recorded_entry, \&next_rand_or_ +recorded_entry, \&_set_to_beginning_entry, \&_set_to_beginning_entry, ); KEY_SWITCH: { if ($key_event ne '') { my $active_key=index $single_key_commands, $key_event; if ($active_key >= 0 ) { $single_key_functions[$active_key] -> ($s, $key_event, $key_ +code); last KEY_SWITCH; } } else { # ($key_event eq '') # ignore modkeys return if ($key_code =~ /^(?:Shift|Control|Alt)_[RL]$/ + || $key_code =~ /^(:Shift|Num|Scroll)_Lock$/); ($key_code eq '') && do { # null event carp("key handler called with no key data\n"); error_beep(); return; }; my $active_key_code=_str_index @key_code_commands, $ke +y_code; if ($active_key_code >= 0) { $key_code_functions[$active_key_code] -> ($s, $key_event, $key_ +code); last KEY_SWITCH; } } { # default (unhandled/unexpected key) printf "Unrecognized key \'%s\', code \'%s\'\n", $key_ +event, $key_code; error_beep(); return; }; } # end KEY_SWITCH; if ($s->disable_auto_advance()) { alarm 0; $s->timer_enabled(0); } else { $s->timer_ticked(0); alarm $s->auto_advance_time; $s->timer_enabled(1); } $s->show_cur_entry_in_imgwin(); }
        Handle_key is what is making some of the "unfound" calls at this point -- the routines in the "jump table"...but it does not seem the jump table is at fault, since "q" (the quit action) properly calls the _quit function:    sub _quit() { $_[0]->write_db(); exit 0; } and fails trying to call "write_db" on exit. "write_db" is a method in a parent class.

        Regardless of call syntax, Perl isn't searching my @ISA info for parent classes. If I am in the debugger before the "$s->write_db()" statement in "_quit()" and use the debugger's "m" command to print out available methods, it finds the parental method, but not when executed.

        Perhaps this is a bug? I.e. shouldn't the debugger be using the same search method as that used during regular execution?
        L