Throughout this cookbook, you've seen me use Affix::Build to generate shared libraries on the fly from C. However, building shared libraries isn't a concept limited to just C so neither are the capabilities of Affix::Build.

Affix::Build, first introduced in our very first chapter, is a cross-platform, multi-lingual compilation wrapper. While it supports over 15 languages (including Rust, Go, Fortran, and D), it is particularly useful for C and C++ because it abstracts away the differences between GCC, Clang, and MSVC, handles operating system extensions (.dll, .so, .dylib), automatically locates the correct driver to link the standard libraries properly, and applies critical flags like -fPIC where required.

In this chapter, we'll demonstrate that as we build a library that uses the C++ Standard Library (STL) to reverse a string in place.

The Recipe

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

# 1. Configure the Compiler
# We enable debug mode to see the underlying compiler commands
my $compiler = Affix::Build->new( name => 'str_util', debug => 1 );

# 2. Add C++ Source
# We pass a reference to a string containing the source code.
# We must specify 'lang => cpp' so the compiler knows to use a C++ driver.
$compiler->add( \<<~'CPP', lang => 'cpp' );
    #include <algorithm>
    #include <string>
    #include <cstring>

    extern "C" {
        // We use C linkage so Affix can find the symbol easily
        void reverse_it(char* buffer) {
            if (!buffer) return;

            // Use high-level C++ features
            std::string s(buffer);
            std::reverse(s.begin(), s.end());

            // Copy back to the raw buffer
            std::strcpy(buffer, s.c_str());
        }
    }
    CPP

# 3. Compile and Link
# This generates the shared object in a temp folder and returns the path.
my $lib_path = $compiler->link;
say 'Library compiled to: ' . $lib_path;

# 4. Bind and Call
affix $lib_path, 'reverse_it', [String] => Void;
my $text = 'Affix makes C++ easy';
reverse_it($text);
say $text;

Output:

[Affix] Exec: g++ -shared C:/Users/S/AppData/Local/Temp/Yx9npzzak9/source_001.cpp -o C:/Users/S/AppData/Local/Temp/Yx9npzzak9/str_util.dll.1
Library compiled to: C:/Users/S/AppData/Local/Temp/Yx9npzzak9/str_util.dll.1
ysae ++C sekam xiffA

How It Works

Bonus: The Polyglot Strategy

Affix::Build can mix languages in a single library. If you add files from different languages (e.g., C and Rust), the compiler switches strategies:

  1. It compiles every source file into a static object file (.o or .a) using the appropriate compiler for each language (rustc for Rust, cc for C, etc.).
  2. It invokes the system linker to combine all static objects into one shared library.
# Example: Using a Rust function inside a C wrapper
$compiler->add( 'src/calc.rs' );  # Contains #[no_mangle] pub extern "C" fn add...
$compiler->add( 'src/main.c' );   # Calls 'add' from Rust
$compiler->link;                  # Links them into one DLL

We'll revisit this concept in future chapters.

Kitchen Reminders