DOKK / manpages / debian 10 / libxs-object-magic-perl / XS::Object::Magic.3pm.en
XS::Object::Magic(3pm) User Contributed Perl Documentation XS::Object::Magic(3pm)

XS::Object::Magic - Opaque, extensible XS pointer backed objects using "sv_magic"

        package MyObject;
        use XS::Object::Magic;
        sub new {
                my $class = shift;
                # create any object representation you like
                my $self = bless {}, $class;
                $self->build_struct;
                return $self;
        }
        # or using Moose
        package MyObject;
        use Moose;
        sub BUILD {
                shift->build_struct;
        }
        # then in XS
        MODULE = MyObject  PACKAGE = MyObject
        void build_struct (SV *self)
                PREINIT:
                        my_struct_t *thingy;
                CODE:
                        thingy = create_whatever();
                        /* note that we dereference self first. This
                         * can be done using an XS typemap of course */
                        xs_object_magic_attach_struct(aTHX_ SvRV(self), thingy);
        void foo (SV *self)
                PREINIT:
                        my_struct_t *thingy;
                INIT:
                        thingy = xs_object_magic_get_struct_rv(aTHX_ self);
                CODE:
                        my_struct_foo(thingy); /* delegate to C api */
        /* using typemap */
        void foo (my_struct_t *thingy)
                CODE:
                        my_struct_foo(thingy);
        /* or better yet */
        PREFIX = my_struct_
        void
        my_struct_foo (thingy)
                my_struct_t *thingy;
        /* don't forget a destructor */
        void
        DESTROY (my_struct_t *thingy)
                CODE:
                        Safefree(thingy);
                        /* note that xs_object_magic_get_struct() will
                         * still return a pointe which is now invalid */

This way of associating structs with Perl space objects is designed to supercede Perl's builtin "T_PTROBJ" with something that is designed to be:

The association of the pointer using "sv_magicext" can be done on any data type, so you can associate C structs with any representation type.

This means that you can add pointers to any object (hand coded, Moose or otherwise), while still having instance data in regular hashes.

The C pointer is neither visible nor modifiable from Perl space.

This prevents accidental corruption which could lead to segfaults using "T_PTROBJ" (e.g. "$$ptr_obj = 0").

When called on the object reference it will check that the "sv" is a reference, dereference it and return the associated pointer using "xs_object_magic_get_struct".

Basically the same as "xs_object_magic_get_struct(aTHX_ SvRV(sv)" but croaks if no magic was found.

Note that storing a "NULL" pointer will not cause an error.

Fetches the pointer associated with "sv".

Returns "NULL" if no pointer is found. There is no way to distinguish this from having a "NULL" pointer.

Fetches the appropriate "MAGIC" entry for the struct pointer storage from "sv".

This lets you manipulate "mg-"mg_ptr> if you need to.

Associates "ptr" with "sv" by adding a magic entry to "sv".
Convenience function that creates a hash object blessed to "stash" and associates it with "ptr".

Can be used to easily create a constructor:

        SV *
        new(char *class)
                CODE:
                        RETVAL = xs_object_magic_create(
                                (void *)test_new(),
                                gv_stashpv(class, 0)
                        );
                OUTPUT: RETVAL
    
Returns 1 if the SV has XS::Object::Magic magic, 0 otherwise.
Returns 1 if the SV references an SV that has XS::Object::Magic magic, 0 otherwise.

This lets you write a quick predicate method, like:

    void
    my_struct_has_struct (self)
            SV *self;
            PPCODE:
                    EXTEND(SP, 1);
                    if(xs_object_magic_has_struct_rv(aTHX_ self))
                            PUSHs(&PL_sv_yes);
                    else
                            PUSHs(&PL_sv_no);
    

Then you can check for the existence of your struct from the Perl side:

    if( $object->has_struct ) { ... }
    
Removes the XS::Object::Magic magic from the given SV. Returns 1 if something is removed, 0 otherwise.
Likes "xs_object_magic_detach_struct", but takes a reference to the magic-containing SV instead of the SV itself. The reference to the SV is typically $self.

Returns 0 if the SV is not a reference, otherwise returns whatever "xs_object_magic_detach_struct" returns.

The included typemap provides a "T_PTROBJ_MG" entry which only supports the "INPUT" conversion.

This typemap entry lets you declare methods that are invoked directly on the associated pointer. In your own typemap add an entry:

        TYPEMAP
        my_pointer_t *  T_PTROBJ_MG

and then you can use "my_pointer_t" as the argument type of the invocant:

        I32
        method (self)
                my_pointer_t *self;
                CODE:
                        ...

Note that there is no "OUTPUT" conversion. In order to return your object you need to use ST(0) or some other means of getting the invocant.

<http://github.com/nothingmuch/xs-object-magic>

Florian Ragwitz, Yuval Kogman

        Copyright (c) 2009 Florian Ragwitz, Yuval Kogman. All rights reserved
        This program is free software; you can redistribute
        it and/or modify it under the same terms as Perl itself.
2018-11-01 perl v5.28.0