Ancient
view release on metacpan or search on metacpan
lib/object.pm view on Meta::CPAN
that bypass Perl callback overhead entirely (~5 cycles vs ~100 cycles).
=head3 C API Reference
Include C<object_types.h> in your XS module:
#include "object_types.h"
=head4 object_register_type_xs
void object_register_type_xs(pTHX_ const char *name,
ObjectTypeCheckFunc check,
ObjectTypeCoerceFunc coerce);
Register a type with C-level check and optional coercion functions.
Call from your BOOT section. The type name can then be used in
C<object::define()> slot specifications.
Parameters:
=over 4
=item * C<name> - Type name (e.g., "PositiveInt", "Email")
=item * C<check> - C function to validate values (required)
=item * C<coerce> - C function to coerce values (optional, pass NULL)
=back
=head4 ObjectTypeCheckFunc
typedef bool (*ObjectTypeCheckFunc)(pTHX_ SV *val);
Type check function signature. Return true if value passes the check.
=head4 ObjectTypeCoerceFunc
typedef SV* (*ObjectTypeCoerceFunc)(pTHX_ SV *val);
Type coercion function signature. Return the coerced value (may be
the same SV or a new mortal). Return NULL if coercion fails.
=head4 object_get_registered_type
RegisteredType* object_get_registered_type(pTHX_ const char *name);
Look up a registered type by name. Returns NULL if not found.
Useful for introspection or chaining type checks.
=head3 Complete Example
/* MyTypes.xs */
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "object_types.h"
static bool check_positive_int(pTHX_ SV *val) {
if (!SvIOK(val) && !(SvPOK(val) && looks_like_number(val)))
return false;
return SvIV(val) > 0;
}
static bool check_email(pTHX_ SV *val) {
if (SvROK(val)) return false;
STRLEN len;
const char *pv = SvPV(val, len);
const char *at = memchr(pv, '@', len);
return at && at != pv && at != pv + len - 1;
}
static SV* coerce_trim(pTHX_ SV *val) {
STRLEN len;
const char *pv = SvPV(val, len);
const char *start = pv;
const char *end = pv + len;
while (start < end && isSPACE(*start)) start++;
while (end > start && isSPACE(*(end-1))) end--;
return sv_2mortal(newSVpvn(start, end - start));
}
MODULE = MyTypes PACKAGE = MyTypes
BOOT:
object_register_type_xs(aTHX_ "PositiveInt", check_positive_int, NULL);
object_register_type_xs(aTHX_ "Email", check_email, NULL);
object_register_type_xs(aTHX_ "TrimmedStr", NULL, coerce_trim);
Usage in Perl:
use MyTypes; # Registers types in BOOT
use object;
object::define('User',
'id:PositiveInt:required',
'email:Email',
'bio:TrimmedStr',
);
my $user = new User id => 42, email => 'user@example.com';
=head3 Performance Tiers
Type Source Check Cost Total Overhead
--------------------------------------------------------
Built-in (Str, Int) ~0 cycles inline switch
Registered C function ~5 cycles function pointer
Perl callback ~100 cycles call_sv overhead
=head3 Linking
Your XS module needs to link against the object module. The functions
are exported with C<PERL_CALLCONV> visibility.
=head2 new $class @args
Create a new object. Supports positional or named arguments.
my $cat = new Cat 'Whiskers', 3; # positional
( run in 0.684 second using v1.01-cache-2.11-cpan-39bf76dae61 )