1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
=head1 NAME
NewClass - adding a new class to wxPerl
=head1 CHECKLIST
=over 4
=item * Are there constants or events that need to be wrapped?
see L</"COSTANTS"> and L</"EVENTS">.
=item * Is the class is derived from wxObject, from wxEvtHandler or from
another class?
see L</"CHOOSING A TYPEMAP">.
=item * Are class instances destroyed by wxWidgets or should they be
garbage collected like normal Perl objects?
see L</"DESTRUCTORS AND THREADS">.
=item * Does the class have overloaded methods?
see L</"OVERLOADING">.
=item * Does the class have virtual methods that should be overridable
from Perl?
see L</"VIRTUAL METHODS">.
=back
=head1 SKELETON
Add a new file F<XS/NewClass.xsp> and update the F<MANIFEST>. Choose
a relevant F<.xs> file in the top level directory (es. F<Controls.xs>)
and add this line:
INCLUDE_COMMAND: $^X -MExtUtils::XSpp::Cmd -e xspp -- -t typemap.xsp XS/NewClass.xsp
A skeleton for F<NewClass.xsp>:
%module{Wx};
#include <wx/newclass.h> // use the relevant wxWidgets header(s)
%name{Wx::NewClass} class wxNewClass : public wxSomeBaseClass
{
# constructors see the CONSTRUCTORS section
wxNewClass( wxWindow* some_window, const wxString& str );
# destructors
~wxNewClass();
# methods
wxString GetString() const;
void SetString( const wxString& str );
};
Add the typemap definition to F<typemap.tmpl>. See L</"CHOOSING A
TYPEMAP">.
=head1 CHOOSING A TYPEMAP
There are five typemaps that should work for most wxWidgets objects:
=over 4
=item * C<O_NON_WXOBJECT>
for all classes that do not derive from C<wxObject> AND do not need to
be garbage collected.
=item * C<O_NON_WXOBJECT_THR>
for all classes that do not derive from C<wxObject> AND need to be
garbage collected (see L</"DESTRUCTORS AND THREADS">).
=item * C<O_WXOBJECT>
for all classes that derive from C<wxObject> AND do not need to be
garbage collected.
=item * C<O_WXOBJECT_THR>
for all classes derived from C<wxObject> AND need to be garbage
collected (see L</"DESTRUCTORS AND THREADS">).
=item * C<O_WXEVTHANDLER>
for all classes that derive from C<wxEvtHandler>. See also
L</"CONSTRUCTORS">.
=back
=head1 CONSTRUCTORS
For C<O_WXEVTHANDLER> typemaps, there is some additional code that
needs to be added to the constructor:
wxNewClass( wxWindow* some_window, const wxString& str )
%code{% RETVAL = new wxNewClass( some_window, str );
wxPli_create_evthandler( aTHX_ RETVAL, CLASS );
%};
=head1 DESTRUCTORS AND THREADS
For many classes not derived from C<wxEvtHandler> you need to add a
destructor to free the C++ object when the Perl object is garbage
collected. At the XS++ level this means adding
~wxNewClass();
to the class definition, but there is a catch: the Perl threading
model.
Without going into details, this is needed for Perl threads compatibility:
=over 4
=item * Use the correct typemap
choose either C<O_NON_WXOBJECT_THR> or C<O_WXOBJECT_THR>.
=item * Implement a C<CLONE> method
add this code inside the class declaration:
%{
static void
wxNewClass::CLONE()
CODE:
wxPli_thread_sv_clone( aTHX_ CLASS, (wxPliCloneSV)wxPli_detach_object );
%}
=item * Fix the destructor.
modify the destructor like this:
~wxNewClass()
%code%{ wxPli_thread_sv_unregister( aTHX_ "Wx::NewClass", THIS, ST(0) );
delete THIS;
%};
=back
=cut
|