---
name: "XS::Object::Magic"
section: "3pm"
platform: "linux"
package: "libxs-object-magic-perl"
version: "0.05-3+b1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/XS::Object::Magic"
---

# XS::Object::Magic(3pm)

Opaque, extensible XS pointer backed objects using "sv\_magic"

## NAME

XS::Object::Magic - Opaque, extensible XS pointer backed objects using "sv\_magic"

## VERSION

version 0.05

## 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;
                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 */
```

## DESCRIPTION

This way of associating structs with Perl space objects is designed to supersede 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
  ```

- int xs\_object\_magic\_has\_struct(aTHX\_ SV \*sv)

  Returns 1 if the SV has XS::Object::Magic magic, 0 otherwise.

- int xs\_object\_magic\_has\_struct\_rv(aTHX\_ SV \*self)

  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 ) { ... }
  ```

- int xs\_object\_magic\_detach\_struct(aTHX\_ SV \*sv, void \*ptr)

  Removes the XS::Object::Magic magic with attached pointer `"ptr"` from the given SV.  Returns the number of elements removed if something is removed, 0 otherwise.

  Supplying NULL as `"ptr"` will result in all XS::Object::Magic magic being removed.

- int xs\_object\_magic\_detach\_struct\_rv(aTHX\_ SV \*self, void \*ptr)

  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.

  `"ptr"` is passwd to xs\_object\_magic\_detach\_struct unmodified.

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

## SUPPORT

Bugs may be submitted through the RT bug tracker \<https://rt.cpan.org/Public/Dist/Display.html?Name=XS-Object-Magic\> (or bug-XS-Object-Magic@rt.cpan.org \<mailto:bug-XS-Object-Magic@rt.cpan.org\>).

## AUTHOR

יובל קוג'מן (Yuval Kogman) \<nothingmuch@woobling.org\>

## CONTRIBUTORS

- •

  Florian Ragwitz \<rafl@debian.org\>

- •

  Jonathan Rockway \<jon@jrock.us\>

- •

  Karen Etheridge \<ether@cpan.org\>

- •

  Emmanuel Rodriguez \<emmanuel.rodriguez@gmail.com\>

- •

  Jeremiah C. Foster \<jeremiah@jeremiahfoster.com\>

## COPYRIGHT AND LICENCE

This software is copyright (c) 2009 by יובל קוג'מן (Yuval Kogman).

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
