Affix

 view release on metacpan or  search on metacpan

lib/Affix.pod  view on Meta::CPAN

    my $val = 42;
    sv_dump($val);
    # Exposes IV flags, memory addresses of the SV head, etc.

=head2 Advanced Debugging

=head3 C<set_destruct_level( $level )>

Sets the internal C<PL_perl_destruct_level> variable.

When testing XS/FFI code for memory leaks using tools like Valgrind or AddressSanitizer, you often want Perl to
meticulously clean up all global memory during its destruction phase (otherwise the leak checker will be flooded with
false-positive "leaks" that are actually just memory Perl intentionally leaves to the OS to reclaim).

    # Call this at the start of your script when running under Valgrind
    set_destruct_level(2);

=head1 COMPANION MODULES

Affix ships with two powerful companion modules to streamline your FFI development:

=over

=item * L<B<Affix::Wrap>|Affix::Wrap>: Parses C/C++ headers using the Clang AST to automatically generate Affix bindings for entire libraries.

=item * L<B<Affix::Build>|Affix::Build>: A polyglot builder that compiles inline C, C++, Rust, Zig, Go, and 15+ other languages into dynamic libraries you can bind instantly.

=back

=head1 THREAD SAFETY & CONCURRENCY

Affix bridges Perl (a single-threaded interpreter, generally) with libraries that may be multi-threaded. This creates
potential hazards that you must manage.

=head2 1. Initialization Phase vs. Execution Phase

Functions that modify Affix's global state are B<not thread-safe>. You must perform all definitions in the main thread
before starting any background threads or loops in the library.

Unsafe operations that you should never call from Callbacks or in a threaded context:

=over

=item * C<affix( ... )> - Binding new functions.

=item * C<typedef( ... )> - Registering new types.

=back

=head2 2. Callbacks

When passing a Perl subroutine as a C<Callback>, avoid performing complex Perl operations like loading modules or
defining subs inside callbacks triggered on a foreign thread. Such callbacks should remain simple: process data, update
a shared variable, and return.

If the library executes the callback from a background thread (e.g., window managers, audio callbacks), Affix attempts
to attach a temporary Perl context to that thread. This should be sufficient but Perl is gonna be Perl.

=head1 RECIPES & EXAMPLES

See L<The Affix Cookbook|https://github.com/sanko/Affix.pm/discussions/categories/recipes> for comprehensive guides to
using Affix.

=head2 Linked List Implementation

    # C equivalent:
    # typedef struct Node {
    #     int value;
    #     struct Node* next;
    # } Node;
    # int sum_list(Node* head);

    typedef 'Node'; # Forward declaration for recursion
    typedef Node => Struct[
        value => Int,
        next  => Pointer[ Node() ]
    ];

    # Create a list: 1 -> 2 -> 3
    my $list = {
        value => 1,
        next  => {
            value => 2,
            next  => {
                value => 3,
                next  => undef # NULL
            }
        }
    };

    # Passing to a function that processes the head
    affix $lib, 'sum_list', [ Pointer[Node()] ] => Int;
    say sum_list($list);

=head2 Interacting with C++ Classes (vtable)

    # Manual call to a vtable entry
    # Suppose $obj_ptr is a pointer to a C++ object
    my $vtable = cast($obj_ptr, Pointer[ Pointer[Void] ]);
    my $func_ptr = $vtable->[0]; # Get first method address

    # Bind and call
    my $method = wrap undef, $func_ptr, [Pointer[Void], Int] => Void;
    $method->($obj_ptr, 42);

=head1 SEE ALSO

L<FFI::Platypus>, L<C::DynaLib>, L<XS::TCC>, L<C::Blocks>

All the heavy lifting is done by L<infix|https://github.com/sanko/infix>, my JIT compiler and type introspection
engine.

=head1 AUTHOR

Sanko Robinson E<lt>sanko@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2023-2026 by Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0.



( run in 0.580 second using v1.01-cache-2.11-cpan-39bf76dae61 )