The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

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

SYNOPSIS

        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 = 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 */

DESCRPTION

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:

Extensible

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.

Opaque

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).

C API

void *xs_object_magic_get_struct_rv(aTHX_ SV *sv)

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.

void *xs_object_magic_get_struct(aTHX_ SV *sv)

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.

MAGIC *xs_object_magic_get_mg (aTHX_ SV *sv)

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

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

void xs_object_magic_attach_struct(aTHX_ SV *sv, void *ptr)

Associates ptr with sv by adding a magic entry to sv.

SV *xs_object_magic_create(aTHX_ void *ptr, HV *stash)

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

TYPEMAP

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.

VERSION CONTROL

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

AUTHOR

Florian Ragwitz, Yuval Kogman

COPYRIGHT & LICENSE

        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.