NewClass

From WxPerl Wiki
Jump to: navigation, search

=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</"CONSTANTS"> 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 (eg. 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">.

If adding a class related to one of the wxPerl submodules (C<Wx::RichText>, C<Wx::Html>, ...) add the F<.xsp> file to the relevant subdirectory and modify the F<.xs> and F<typemap> files in that subdirectory.

=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

=head1 VIRTUAL METHODS

The wrapping of virtual functions whose arguments are simple C++ types (integrals, bool, floating point) and common wxWidgets types (wxString) should be automatic: at the top of the file, load the plugin that handles virtual methods

   %loadplugin{build::Wx::XSP::Virtual};

and decorate virtual/pure virtual methods using the C<%Virtual> directive

   // pure virtual
   virtual wxString GetTitle() const = 0 %Virtual{pure};
   // virtual, not pure
   virtual int GetBestFittingWidth(unsigned int idx) const %Virtual;

If the class contains pure virtual methods, it will be marked as abstract, and it will have no constructors.

For abstract classes, XS++ will create an additional Perl-level class, called C<< Wx::Pl<classname> >>; in order to override the virtual methods, you must derive from this class, and not from C<< Wx::<classname> >>.

TODO allow changing the default behaviour for abstract/concrete classes

TODO allow overriding the class name

TODO allow specifying custom code

TODO handle multiple return values

TODO customized type mapping

=cut