=head1 NAME
XS::Framework::Manual::recipe03 - XS::Framework basics
=cut
=head1 DESCRIPTION
Let's assume that there in an external C++ class which follows singleton
pattern. Also, let's assume that it returns C<const> singleton, i.e. all
methods of C++ class are marked as C<const>. Here is an example of such
class
struct TimezoneRecipe03 {
const char* get_name() const { return name; }
static const TimezoneRecipe03& get_instance() {
static TimezoneRecipe03* instance = new TimezoneRecipe03();
return *instance;
}
private:
TimezoneRecipe03() { name = "Europe/Minsk"; }
const char* name;
};
It is possible to specialize typemaps with I<const typemap>. Althought,
Perl does not have notion of const objects, it has notion of read-only
SV*, so invoking non-const method on read-only SV* wrapper leads
to C<cannot modify read-only object> error. Here is an example of typemap
namespace xs {
template <>
struct Typemap<const TimezoneRecipe03*> : TypemapObject<const TimezoneRecipe03*, const TimezoneRecipe03*, ObjectTypeForeignPtr, ObjectStorageIV, StaticCast> {
// (1) (2) (3) (4) (5)
static std::string package () { return "MyTest::Cookbook::TimezoneRecipe03"; }
};
}
Here (1 .. 3) shows how to define typemap for const object. Please, not that
non-const typemap is auto-deduced from const typemap.
As the perl side does not owns the pointer, and, hence, does not need to
C<delete> it, we can use C<ObjectTypeForeignPtr> lifetime policy (4) and
C<ObjectStorageIV> storage policy (5). There is no leak in missing
C<DESTROY> method in xs-adapter below. Please note, that it is assumed that
no further class extension is possible (see limitations of C<ObjectStorageIV>
storage policy).
The xs-adapter code should look like:
MODULE = MyTest PACKAGE = MyTest::Cookbook::TimezoneRecipe03
PROTOTYPES: DISABLE
const char* TimezoneRecipe03::get_name() : const;
# (5) (6)
const TimezoneRecipe03* get_instance() { RETVAL = &TimezoneRecipe03::get_instance(); }
# (7)
It is rather trivial; hovewer, please, pay attention to a few nuances: the
C<const> methods should be marked as attribute C<const> (6) after colon (5).
The returned pointer (7) should also be marked with C<const>.