The fastest way to use Affix::Wrap is Runtime Wrapping. In this workflow, you parse the headers and bind the functions immediately when your script starts. This is ideal for rapid prototyping, internal scripts, or testing, as you don't need to generate a separate .pm file.
The Recipe
In this demo, we'll use Affix::Build to build a library and Affix::Wrap to wrap it instantly.
use v5.40;
no warnings 'once';
use Affix qw[:all];
use Affix::Build;
use Affix::Wrap;
use Path::Tiny;
# 1. Setup the C Project
my $dir = Path::Tiny->tempdir( CLEANUP => 0 );
my $src = $dir->child('physics.c');
my $hdr = $dir->child('physics.h');
# A header with documentation
$hdr->spew_utf8(<<~'H');
typedef struct { double x, y, z; } Vector3;
/**
* Adds two vectors.
*/
Vector3 vec_add(Vector3 a, Vector3 b);
// Global gravity constant
extern double GRAVITY;
H
# Implementation
$src->spew_utf8(<<~'C');
#include "physics.h"
#ifdef _WIN32
__declspec(dllexport)
#endif
double GRAVITY = 9.81;
#ifdef _WIN32
__declspec(dllexport)
#endif
Vector3 vec_add(Vector3 a, Vector3 b) {
Vector3 r = { a.x + b.x, a.y + b.y, a.z + b.z };
return r;
}
C
# 2. Compile the library
my $compiler = Affix::Build->new( build_dir => $dir );
$compiler->add($src);
my $lib_path = $compiler->link;
# 3. The Magic: Bind it!
Affix::Wrap->new( project_files => [$hdr], include_dirs => [$dir] )->wrap($lib_path);
# 4. Use it
# The functions and typedefs are now installed in our package!
say "Gravity is: $main::GRAVITY";
my $v1 = { x => 1, y => 2, z => 3 };
my $v2 = { x => 4, y => 5, z => 6 };
# Affix::Wrap automatically handled the Struct definition for Vector3
my $v3 = vec_add( $v1, $v2 );
say "Result: $v3->{x}, $v3->{y}, $v3->{z}";
Output:
Gravity is: 9.81
Result: 5, 7, 9
How It Works
->wrap($lib)This method iterates over every node found in the AST.- Typedefs/Structs: It calls
Affix::typedef, registering types likeVector3so they can be used in signatures. - Variables: It calls
Affix::pin, tying the Perl variable$GRAVITYto the symbol in the shared library. - Functions: It calls
Affix::affix, creating the Perl subroutinevec_add.
- Typedefs/Structs: It calls
Note that we didn't write a single Struct[...] or affix signature manually.
Kitchen Reminders
-
Namespaces: By default,
wrapinstalls symbols into the caller's package. If you want to keep things clean, you can wrap into a dedicated class:package Physics { Affix::Wrap->new(...)->wrap($lib, 'Physics'); } say Physics::vec_add(...);