Provided by: libwx-perl_0.9922-2_amd64
NAME
NewClass - adding a new class to wxPerl
CHECKLIST
• Are there constants or events that need to be wrapped? see "CONSTANTS" and "EVENTS". • Is the class is derived from wxObject, from wxEvtHandler or from another class? see "CHOOSING A TYPEMAP". • Are class instances destroyed by wxWidgets or should they be garbage collected like normal Perl objects? see "DESTRUCTORS AND THREADS". • Does the class have overloaded methods? see "OVERLOADING". • Does the class have virtual methods that should be overridable from Perl? see "VIRTUAL METHODS".
SKELETON
Add a new file XS/NewClass.xsp and update the MANIFEST. Choose a relevant .xs file in the top level directory (eg. Controls.xs) and add this line: INCLUDE_COMMAND: $^X -MExtUtils::XSpp::Cmd -e xspp -- -t typemap.xsp XS/NewClass.xsp A skeleton for 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 typemap.tmpl. See "CHOOSING A TYPEMAP". If adding a class related to one of the wxPerl submodules ("Wx::RichText", "Wx::Html", ...) add the .xsp file to the relevant subdirectory and modify the .xs and typemap files in that subdirectory.
CHOOSING A TYPEMAP
There are five typemaps that should work for most wxWidgets objects: • "O_NON_WXOBJECT" for all classes that do not derive from "wxObject" AND do not need to be garbage collected. • "O_NON_WXOBJECT_THR" for all classes that do not derive from "wxObject" AND need to be garbage collected (see "DESTRUCTORS AND THREADS"). • "O_WXOBJECT" for all classes that derive from "wxObject" AND do not need to be garbage collected. • "O_WXOBJECT_THR" for all classes derived from "wxObject" AND need to be garbage collected (see "DESTRUCTORS AND THREADS"). • "O_WXEVTHANDLER" for all classes that derive from "wxEvtHandler". See also "CONSTRUCTORS".
CONSTRUCTORS
For "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 ); %};
DESTRUCTORS AND THREADS
For many classes not derived from "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: • Use the correct typemap choose either "O_NON_WXOBJECT_THR" or "O_WXOBJECT_THR". • Implement a "CLONE" method add this code inside the class declaration: %{ static void wxNewClass::CLONE() CODE: wxPli_thread_sv_clone( aTHX_ CLASS, (wxPliCloneSV)wxPli_detach_object ); %} • Fix the destructor. modify the destructor like this: ~wxNewClass() %code%{ wxPli_thread_sv_unregister( aTHX_ "Wx::NewClass", THIS, ST(0) ); delete THIS; %};
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 %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 "Wx::Pl<classname>"; in order to override the virtual methods, you must derive from this class, and not from "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