You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sometimes, you don't have a pre-existing .dll or .so file. Sometimes, you just have an idea, a heavy mathematical loop, or a snippet of C code you found on Stack Overflow, and you want to run it right now inside your Perl script.
This is where Affix::Build shines. It turns your Perl script into a build system, a linker, and a loader, all in about five lines of code.
Let's look at a classic "Hello World" of pointer manipulation: the Integer Swap.
The Recipe
use v5.40;
use Affix;
use Affix::Build;
# 1. Spin up the compilermy$c = Affix::Build->new();
# 2. Add some C code directly into the script$c->add( \<<~'', lang=>'c' );
void swap(int *a, int *b) { int tmp = *b; *b = *a; *a = tmp; }# 3. Compile, Link, and Bind
affix $c->link, swap=> [ Pointer [Int], Pointer [Int] ] => Void;
# 4. Profitmy$a = 1;
my$b = 2;
say"Before: [a,b] = [$a, $b]";
# Pass references so C can write back to Perl
swap( \$a, \$b );
say"After: [a,b] = [$a, $b]";
How It Works
This creates a seamless bridge between the two languages. Here is what is happening under the hood:
The Builder
Affix::Build->new() creates a temporary workspace. It detects your operating system (Windows, Linux, macOS, BSD) and hunts for a viable compiler chain (GCC, Clang, MSVC). You don't need to configure Makefiles or worry about linker flags; the class handles the heavy lifting.
The Source
We pass the source code as a reference to a string (\<<~''>). This tells the compiler, "I'm not giving you a filename; I'm giving you the raw code." We specify lang => 'c', but Affix::Build is a polyglotΓÇöit could just as easily have been cpp, rust, or fortran.
The Link
Calling $c->link triggers the build process. It writes your source to a temp file, compiles it into an object file, and links it into a dynamic library. It returns the absolute path to that library (e.g., /tmp/affix_lib.so).
We pass that path immediately to affix( ... ), binding the symbol swap.
The Types
This is the most critical part of this recipe:
[ Pointer [Int], Pointer [Int] ]
If we had defined this as [ Int, Int ], Affix would have passed the values1 and 2 to C. The C code would have swapped those values in its own local stack and returned, leaving our Perl variables untouched.
By specifying that these are Pointers, we tell Affix we expect a memory address.
The Execution
Because we defined the types as Pointers, we must pass B to our Perl scalars:
swap( \$a, \$b );
Affix takes the memory address of the value held in the scalar $a, passes it to C, and allows the C code to overwrite the memory directly. When swap returns, $a sees the data that was previously in $b and vice versa. Their values are swapped!
Kitchen Reminders
The chef would like to remind you of things you should have noted or learned from this recipe.
Compiler Required
While Affix works on any machine, Affix::Build obviously requires a C compiler (like gcc, clang, or Visual Studio) to be in your system's PATH.
Automatic Cleanup
By default, Affix::Build creates a temporary directory for the build artifacts and leaves it on disk when your script ends so you can inspect the generated C files or the .so library for debugging. If you want that directory wiped when the script exits, pass clean => 1 to the constructor:
C is unforgiving. If you tell Affix the argument is a Pointer[Int], but you pass a string like "Hello", Affix will try to make it work, but the C code effectively interprets the bytes of that string as an integer. Always match your Perl data types to your Affix definitions.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Sometimes, you don't have a pre-existing
.dllor.sofile. Sometimes, you just have an idea, a heavy mathematical loop, or a snippet of C code you found on Stack Overflow, and you want to run it right now inside your Perl script.This is where
Affix::Buildshines. It turns your Perl script into a build system, a linker, and a loader, all in about five lines of code.Let's look at a classic "Hello World" of pointer manipulation: the Integer Swap.
The Recipe
How It Works
This creates a seamless bridge between the two languages. Here is what is happening under the hood:
Affix::Build->new()creates a temporary workspace. It detects your operating system (Windows, Linux, macOS, BSD) and hunts for a viable compiler chain (GCC, Clang, MSVC). You don't need to configure Makefiles or worry about linker flags; the class handles the heavy lifting.We pass the source code as a reference to a string (
\<<~''>). This tells the compiler, "I'm not giving you a filename; I'm giving you the raw code." We specifylang => 'c', butAffix::Buildis a polyglotΓÇöit could just as easily have beencpp,rust, orfortran.Calling
$c->linktriggers the build process. It writes your source to a temp file, compiles it into an object file, and links it into a dynamic library. It returns the absolute path to that library (e.g.,/tmp/affix_lib.so).We pass that path immediately to
affix( ... ), binding the symbolswap.This is the most critical part of this recipe:
If we had defined this as
[ Int, Int ], Affix would have passed the values1and2to C. The C code would have swapped those values in its own local stack and returned, leaving our Perl variables untouched.By specifying that these are
Pointers, we tell Affix we expect a memory address.Because we defined the types as Pointers, we must pass B to our Perl scalars:
Affix takes the memory address of the value held in the scalar
$a, passes it to C, and allows the C code to overwrite the memory directly. Whenswapreturns,$asees the data that was previously in$band vice versa. Their values are swapped!Kitchen Reminders
The chef would like to remind you of things you should have noted or learned from this recipe.
While
Affixworks on any machine,Affix::Buildobviously requires a C compiler (likegcc,clang, or Visual Studio) to be in your system'sPATH.By default,
Affix::Buildcreates a temporary directory for the build artifacts and leaves it on disk when your script ends so you can inspect the generated C files or the.solibrary for debugging. If you want that directory wiped when the script exits, passclean => 1to the constructor:C is unforgiving. If you tell Affix the argument is a
Pointer[Int], but you pass a string like"Hello", Affix will try to make it work, but the C code effectively interprets the bytes of that string as an integer. Always match your Perl data types to your Affix definitions.All reactions