C libraries often use callback functions to delegate logic back to the user. The standard library's qsort is the classic example: it knows how to sort, but it doesn't know how you'd like to compare your data. Affix allows you to pass a standard Perl subroutine (CodeRef) where C expects a function pointer.

The Recipe

Let's sort a list of integers using qsort.

use v5.40;
use Affix;

# 1. Bind qsort
# void qsort(void *base, size_t nmemb, size_t size,
#            int (*compar)(const void *, const void *));
#
# The callback signature is defined inside the argument list.
# Callback[ [Args...] => ReturnType ]
affix libc, 'qsort', [
    Pointer [Int], Size_t, Size_t,    
    Callback [ [ Pointer [Int], Pointer [Int] ] => Int ]
] => Void;

# 2. Prepare Data
# qsort works on a raw memory array.
# We create a C array of integers.
my @nums  = ( 88, 56, 100, 2, 25 );
my $count = scalar @nums;

# 3. Define the Comparator
# C passes us pointers to the two items being compared.
# We must dereference them to get the values.
my $compare_fn = sub ( $p_a, $p_b ) { $$p_a <=> $$p_b };

# 4. Call
# We pass the ArrayRef directly. Affix handles the pointer decay
# and write-back (see Chapter 10).
# sizeof(int) is usually 4.
qsort( \@nums, $count, 4, $compare_fn );
say join ', ', @nums;    # 2, 25, 56, 88, 100

How It Works

Kitchen Reminders