Writing affix signatures manually is great for control, but it becomes tedious when wrapping a library with hundreds of functions and structs. Instead of staring at a .h file and manually translating C types to Affix types, let Affix::Wrap automate it!

Affix::Wrap is a friction-less introspection engine that parses C/C++ header files and builds a structured Abstract Syntax Tree (AST) of the library. It can detect functions, variables, macros, enums, and complex nested structs.

The Drivers

Affix::Wrap uses a dual-driver approach to read C code:

  1. Clang Driver (Preferred): If the clang executable is found in your path, Affix::Wrap uses it to compile the header and dump the AST in JSON format. This is extremely accurate. It handles preprocessor macros, include paths, and complex typedef chains exactly as a C compiler would.
  2. Regex Driver (Fallback): If Clang is missing, it falls back to a pure Perl, regex based parser. This is fast and has zero external dependencies but it may struggle with highly complex C++ templates or obscure preprocessor magic.

The Recipe

This time, let's parse a sample C header to see what Affix::Wrap sees.

use v5.40;
use Affix::Wrap;
use Path::Tiny;
use Data::Dump;

# 1. Create a dummy header file
my $header = Path::Tiny->tempfile( SUFFIX => '.h' );
$header->spew_utf8(<<~'C');
    /**
     * @brief A 2D Point
     */
    typedef struct {
        int x;
        int y;
    } Point;

    #define MAX_POINTS 100

    /**
     * @brief Calculate distance
     * @param p The point to measure
     */
    double distance(Point p);
    C

# 2. Parse the header
my $binder = Affix::Wrap->new( project_files => ["$header"] );
my @nodes  = $binder->parse;

# 3. Inspect the AST
foreach my $node (@nodes) {
    if ( $node isa Affix::Wrap::Function ) {
        say 'Found Function: ' . $node->name;
        say ' - Returns: ' . $node->ret->name;
    }
    elsif ( $node isa Affix::Wrap::Macro ) {
        say 'Found Macro: ' . $node->name . ' = ' . $node->value;
    }
    elsif ( $node isa Affix::Wrap::Typedef ) {
        say 'Found Typedef: ' . $node->name;
        say '  ' . $node->affix_type;
    }
}

Output:

Found Typedef: Point
  typedef Point => Struct[ x => Int, y => Int ]
Found Macro: MAX_POINTS = 100
Found Function: distance
 - Returns: double

How It Works

The parse method returns a list of Affix::Wrap::Entity objects. These objects understand the C types they represent. For example, the Struct object contains a list of Member objects, which in turn hold Type objects.

Affix::Wrap flattens complex relationships. Notice in the C code, Point was a typedef around an anonymous or named struct. Affix::Wrap detects this common pattern and merges them, presenting you with a single named Struct entity.

Kitchen Reminders