Hi,

I attempted to wrap the missing callbacks in wxVListBox and came across the following issues. I've explained at length as info may be useful for someone else like me trying to understand how to help with wxPerl.

An illustrative snippet of my code is

#----------------------------------------------

package MyList;
use base qw( Wx::PlVlistBox );

sub new {
    my $self = shift->SUPER::new( @_ );
    $self->{mycounter} = 100;
    return $self;
}

sub OnDrawItem {
    my( $self, $dc, $rect, $item ) = @_;
    ....
    $self->{mycounter} ++;
    print qq(Counter = $self->{mycounter}\n);
}

#-----------------------------------------------

With Wx 0.98 from CPAN, this fails at
$self->{mycounter} = 100; because $self is not a hash but it is an object of type Wx::VListBox

Looking at the wxPerl code, I figure out that this is because wxPlVlistBox has a typemap of O_WXEVTHANDLER.

If I want Wx::PlVlistBox::new to return me the equivalent of bless {}, $class - I have to add a line to the constructor

wxPli_create_evthandler( aTHX_ RETVAL, CLASS );

amongst other things, when this is parsed by the preprocessors, I get

wxPli_evthandler_2_sv

applied in Wx::PlVlistBox::new so I get back the blessed hash / class I expected.

With that applied everything appears to work as expected - except that the printed output from OnDrawItem starts at 1 - not 100. It increments as expected on each call though.

Investigation tells me the following.

The contructor for my Wx::PlVlistBox based class calls

wxPli_make_object

this returns  - sv_bless( ret, stash )

where ret is my way of accessing the underlying wxWidgets structure directly and stash I can think of as containing what I would get back if I did 'bless {}, $class;' in Perl.

The returned value is stored in wxPerl's class for holding on to object data - in member m_self.

Within wxPerl, whenever I call a method that is going to return a wxWidgets object, some methods give me the correct 'stash' stored in m_self.

O_WXEVTHANDLER types are a little different.

There is no method added by default to the constructor to convert the the return value to the associated 'stash'. So this explains the first result I got running unaltered code.

When I add wxPli_create_evthandler to the constructor, the following happens.

wxPli_make_object is called again.

wxWidgets provides a two accessors for classes that inherit from wxEvtHandler or use a mixin class wxClientDataContainer.

This gives wrappers for wxWidgets like wxPerl and wxPython somewhere to store their associated data within the wxWidgets object data itself.

So, wxPli_create_evthandler gets a new sv_bless( ret, stash ) and stores this in ->SetClientData.

So there's effectively two sv_bless( ret, stash) values stored.

The original one in m_self and the second one in m_self->GetClientData.
The 'stash' pointers stored therein point to different stashes.

This is fine because all this is happening in the constructor. The methods that return the objects to your Perl code will always call ->GetClientData for objects that inherit from wxEvthandler if client data exists.

Except for the callback code. I think this always returns the stash from m_self and does not call GetClientData.

So, I can make my example code apparently work by giving wxPLVListBox and wxVListBox a typemap of O_WXOBJECT - so there's no use of SetClientData.

But, now of course I have Perl data and no automatic destruction.

So, the first question would be, how do I tell which is the appropriate typemap to use for any given class. Obviously I can only use O_WXEVTHANDLER for objects which inherit from wxEvtHandler. But plenty of classes that inherit from wxEvtHandler also have typemaps of O_WXOBJECT. A general scan of the typemaps tells me that it appears that classes that inherit from wxControl are O_WXEVTHANDLER and classes that are more 'container' classes have a typemap of O_WXOBJECT. (for wxWindow inheriting classes, of course).

O_WXEVTHANDLER looks like the typemap I should always choose if possible.

It appears that I have to use O_WXOBJECT if I want Perl data and Callbacks?

Is this issue quite difficult to solve - and therefore why it is implemented as O_WXEVTHANDLER but without any Perl stash in the first place?

Sorry for the huge post - but hopefully that means replies can be inversely short!

Regards

Mark























































Reply via email to