In C, arrays and pointers are cousins. In function arguments, they are twins. Declaring void func(int a[]) is exactly the same as void func(int *a). However, in Perl and thus in Affix, this isn't the case.

This recipe shows how to pass lists of data to C using the Array type, which handles allocation and copying for you.

The Recipe

We will wrap a C function that sums a zero-terminated array of integers.

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

# 1. Compile C
my $c = Affix::Build->new();
$c->add( \<<~'END', lang => 'c' );
    #include <stdlib.h>

    int array_sum(const int * a) {
        int i, sum;
        if (a == NULL)
            return -1; // Error code for NULL

        // Loop until we hit a 0
        for (i = 0, sum = 0; a[i] != 0; i++)
            sum += a[i];
        return sum;
    }
END

# 2. Bind
# We use Array[Int] to tell Affix to expect a list of numbers.
# Affix handles the C "array decay" (passing as pointer) automatically.
affix $c->link, array_sum => [ Array [Int] ] => Int;

# 3. Call
# Pass undef -> NULL
say "Undef: " . array_sum(undef);    # -1

# Pass [0] -> {0} -> Sums to 0 (Immediate stop)
say "Zero:  " . array_sum( [0] );    # 0

# Pass List -> {1, 2, 3, 0} -> Sums to 6
say "List:  " . array_sum( [ 1, 2, 3, 0 ] );    # 6

How It Works

Kitchen Reminders