Wx::NewClass(3pm) | User Contributed Perl Documentation | Wx::NewClass(3pm) |
NewClass - adding a new class to wxPerl
see "CONSTANTS" and "EVENTS".
see "CHOOSING A TYPEMAP".
see "DESTRUCTORS AND THREADS".
see "OVERLOADING".
see "VIRTUAL METHODS".
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.
There are five typemaps that should work for most wxWidgets objects:
for all classes that do not derive from "wxObject" AND do not need to be garbage collected.
for all classes that do not derive from "wxObject" AND need to be garbage collected (see "DESTRUCTORS AND THREADS").
for all classes that derive from "wxObject" AND do not need to be garbage collected.
for all classes derived from "wxObject" AND need to be garbage collected (see "DESTRUCTORS AND THREADS").
for all classes that derive from "wxEvtHandler". See also "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 ); %};
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:
choose either "O_NON_WXOBJECT_THR" or "O_WXOBJECT_THR".
add this code inside the class declaration:
%{ static void wxNewClass::CLONE() CODE: wxPli_thread_sv_clone( aTHX_ CLASS, (wxPliCloneSV)wxPli_detach_object ); %}
modify the destructor like this:
~wxNewClass() %code%{ wxPli_thread_sv_unregister( aTHX_ "Wx::NewClass", THIS, ST(0) ); delete THIS; %};
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
2020-11-09 | perl v5.32.0 |