In C, arrays passed to functions are often used as output buffers. The function reads data from the array, modifies it in place, and expects the caller to see the changes. In XS, these are defined as IN_OUT parameters. Affix supports this functionality automatically.

The Recipe

We will define a C function that reverses an integer array in place.

use v5.40;
use Affix qw[:all];
use Affix::Build;

# 1. Compile C
my $c = Affix::Build->new();
$c->add( \<<~'END', lang => 'c' );
    // Reverses array 'a' in place
    int array_reverse(int a[], int len) {
        int tmp, i;
        int ret = 0; // Sum of first half (arbitrary logic)
        for (i = 0; i < len / 2; i++) {
            ret += a[i];
            tmp = a[i];
            a[i] = a[len - i - 1];
            a[len - i - 1] = tmp;
        }
        return ret;
    }

    // Wrapper for fixed-size 10-element array
    int array_reverse10(int a[10]) {
        return array_reverse(a, 10);
    }
END
my $lib = $c->link;

# 2. Bind
# Dynamic length array
affix $lib, array_reverse => [ Array[Int], Int ], Int;

# Fixed length array
affix $lib, array_reverse10 => [ Array[Int, 10] ], Int;

# 3. Call (Fixed Size)
my @a = ( 1 .. 10 );
array_reverse10( \@a );
say "@a"; # Output: 10 9 8 7 6 5 4 3 2 1

# 4. Call (Dynamic Size)
my $b = [ 1 .. 20 ];
array_reverse( $b, 20 );
say "@$b"; # Output: 20 19 ... 2 1

How It Works

Kitchen Reminders