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:
- Clang Driver (Preferred): If the
clangexecutable is found in your path,Affix::Wrapuses 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. - 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
- Includes: If your header includes other files (like
<stdio.h>or"my_types.h"), pass their locations to the constructor viainclude_dirs => ['/path/to/includes']. - Documentation:
Affix::Wrapalso captures comments! In the next chapters, we will use this to generate documentation automatically.