NAME

XS::Framework::Manual::recipe03 - XS::Framework basics

DESCRIPTION

Let's assume that there in an external C++ class which follows singleton pattern. Also, let's assume that it returns const singleton, i.e. all methods of C++ class are marked as 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 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 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 delete it, we can use ObjectTypeForeignPtr lifetime policy (4) and ObjectStorageIV storage policy (5). There is no leak in missing DESTROY method in xs-adapter below. Please note, that it is assumed that no further class extension is possible (see limitations of 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 const methods should be marked as attribute const (6) after colon (5). The returned pointer (7) should also be marked with const.