Affix
view release on metacpan or search on metacpan
lib/Affix.pod view on Meta::CPAN
=back
=head2 SIMD Vectors
Vectors are first-class types. You can interact with them using standard B<ArrayRefs> (convenient) or B<Packed Strings>
(high-performance, zero-overhead).
=over
=item * B<C<Vector[ $size, $type ]>>: Create a custom vector (e.g., C<Vector[ 4, Float ]>).
=item * B<Aliases>: C<M256>, C<M256d>, C<M512>, C<M512d>, C<M512i>.
=back
# C: __m256 add_vecs(__m256 a, __m256 b);
affix $lib, 'add_vecs', [ M256, M256 ] => M256;
my $v1 = pack('f8', 1..8);
my $v2 = pack('f8', 10, 20, 30, 40, 50, 60, 70, 80);
my $packed_res = add_vecs( $v1, $v2 );
=head1 MEMORY MANAGEMENT
Allocate, cast, and manage C memory safely from Perl using zero-copy VTable magic. When bridging Perl and C, handling
raw memory safely is critical. Affix uses B<Pins> to manage this boundary.
Affix now features a completely reimagined memory access system using Perl's internal magic to map Perl variables
directly to native C memory. This provides zero-copy performance with the ergonomics of native Perl Hashes and Arrays.
=head2 Managed vs. Unmanaged Memory
Memory in Affix is handled by life lines.
=over
=item * B<Affix::Memory:> Created via C<malloc()> or C<calloc()>. These are root objects. When the Perl variable is destroyed, C<safefree()> is called automatically.
=item * B<Pins:> Created via C<cast()> or pointer dereferencing. These variables do not own the memory, but they hold a reference to a life line to prevent the parent memory from being freed prematurely.
=back
=head2 Allocation & Deallocation
These functions allocate memory on the C heap. Memory allocated via these functions is B<managed by Perl> by default.
=head3 C<malloc( $size )>
Allocates C<$size> bytes of uninitialized memory. Returns a C<Pointer[Void]> pin.
my $ptr = malloc(1024); # Allocates 1KB
=head3 C<calloc( $count, $size )>
Allocates zero-initialized memory for C<$count> elements of C<$size>. Returns a C<Pointer[Void]> pin.
my $ptr = calloc( 10, sizeof(Int) );
my $arr = cast( $ptr, Array[Int, 10] );
=head3 C<realloc( $ptr, $new_size )>
Resizes the memory area pointed to by C<$ptr> to C<$new_size> bytes. The original pin is updated automatically
in-place.
$ptr = realloc( $ptr, 2048 );
=head3 C<strdup( $string )>
Allocates managed memory and copies the Perl string (along with a C<NULL> terminator) into it. Returns a managed
C<Pointer[Char]> pin.
my $str_ptr = strdup("Hello C!");
=head3 C<free( $ptr )>
Manually releases memory.
B<Warning:> Only use this on memory that you exclusively own (e.g., allocated via C<malloc>). Do not call C<free> on
unmanaged pointers returned by C libraries unless the library explicitly transfers ownership to you, or you will cause
a segmentation fault.
free($ptr);
=head3 C<own( $pin )>
Returns true if the given pin is an owned C<Affix::Memory> object (i.e., memory allocated via C<malloc> or C<calloc>
that Perl manages directly). Returns false for unmanaged pins or raw scalars.
if (own($ptr)) {
say "Perl owns this memory; it will be freed automatically.";
}
=head3 C<is_pin( $var )>
Returns true if the variable is currently bound to C memory via C<pin>, C<cast>, or pointer dereferencing. Returns
false for ordinary Perl scalars.
my $x = 42;
say is_pin($x); # false
pin $x, libc(), 'errno', Int;
say is_pin($x); # true
=head2 Lifecycle & Ownership
=head3 C<attach_destructor( $pin, $func_ptr, [$lib] )>
Attaches a custom C function to be called when the Pin is destroyed. This is incredibly useful for C libraries that
require specific cleanup routines (e.g., C<SDL_DestroyWindow>, C<sqlite3_free>).
# Find the address of the library's custom free function
my $free_func = find_symbol($my_lib, 'custom_free');
# When $ptr goes out of scope, Affix will call custom_free($ptr)
attach_destructor($ptr, $free_func, $my_lib);
=head3 C<readonly( $pin, [$bool] )>
Gets or sets the "const" status of a memory pin. If set to true, any attempt to write to that memory from Perl will
throw an exception.
readonly($point, 1);
( run in 1.054 second using v1.01-cache-2.11-cpan-bbc515a03b3 )