Dealing with C strings usually involves asking "Who owns this memory?"

In Perl, strings are values. In C, they are pointers. A common (though not thread-safe) pattern in C libraries is to return a pointer to an internal static buffer. This buffer is overwritten or freed the next time the function is called.

If you were using raw pointers, this would be dangerous; your Perl variable would suddenly change its value or point to freed memory when you made a subsequent API call.

Affix solves this by copying string return values into Perl's memory space immediately.

The Recipe

In this example, we implement a C function that remembers its last result. It frees the old result before allocating a new one. We use a final call with undef to trigger a cleanup.

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

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

    const char * string_reverse(const char * input) {
        // Static pointer persists across function calls
        static char * output = NULL;
        int i, len;

        // Cleanup previous call's memory
        if (output != NULL) {
            free(output);
            output = NULL;
        }

        // Handle "Cleanup Mode" (NULL input)
        if (input == NULL)
            return NULL;

        // Allocate new buffer
        len = strlen(input);
        output = malloc(len + 1);

        // Reverse the string
        for (i = 0; input[i]; i++)
            output[len - i - 1] = input[i];
        output[len] = '\0';

        return output;
    }
END

my $lib = $c->link;

# 2. Bind the function
# String means "const char*" for input and output.
affix $lib, 'string_reverse', [String] => String;

# 3. Use it
# Input:  "\nHello world"
# Output: "dlrow olleH\n"
print string_reverse("\nHello world");

# 4. Cleanup
# Passing undef sends NULL to C, triggering the free() logic.
string_reverse(undef);

How It Works

Kitchen Reminders