Affix

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

- `LongDouble`: Platform-specific extended precision (typically 80-bit on x86 or 128-bit).

### Complex Numbers

- `Complex[ $type ]`: C99 complex numbers (e.g., `Complex[Double]`). In Perl, these map to an `ArrayRef` of two numbers: `[ $real, $imaginary ]`.

## String Types

- **`String`**: Maps to `const char*`. Affix handles UTF-8 encoding (Perl to C) and decoding (C to Perl) automatically.
- **`WString`**: Maps to `const wchar_t*`. Affix automatically handles UTF-16/UTF-32 conversions, including Windows Surrogate Pairs.
- **`StringList`**: Maps a Perl `ArrayRef` of strings to a null-terminated `char**` array (common in C APIs like `execve` or `main(argc, argv)`).
- **`Buffer`**: Maps a mutable `char*` to the raw memory buffer of a Perl scalar. **Zero-copy**. The scalar must have pre-allocated capacity (e.g., `"\0" x 1024`).

## Pointer & Reference Types

### `Pointer[ $type ]`

A pointer to another type. When used as an argument, you can pass a **reference to a scalar** for automatic temporary
allocation and write-back.

```perl
# C: void get_val(int *val);
affix $lib, 'get_val', [ Pointer[Int] ] => Void;
my $val = 0;
get_val(\$val);
say $val; # Updated by C
```

### Specialized Pointers

- **`File`** / **`PerlIO`**: Maps Perl filehandles (Globs or IO objects) to `FILE*` or `PerlIO*`. **Must** be wrapped in a pointer: `Pointer[File]`.
- **`SockAddr`**: Specialized marshalling for packed socket strings (e.g., from `Socket::pack_sockaddr_in`) to `struct sockaddr*`.
- **`SV`**: Direct, low-level access to Perl's internal Interpreter Object (`SV*`). **Must** be wrapped in a pointer: `Pointer[SV]`.

## Aggregate Types

### `Struct[ @members ]`

A C struct, mapped to a Perl `HashRef`.

```perl
# C: typedef struct { int x; int y; } Point;
typedef Point => Struct[ x => Int, y => Int ];
```

### `Union[ @members ]`

A C union, mapped to a Perl `HashRef` with exactly one key.

```perl
# C: union { int key_code; float pressure; };
typedef Event => Union[ key_code => Int, pressure => Float ];
```

### `Packed[ $align, $aggregate ]`

Forces specific byte alignment on a Struct or Union (e.g., `#pragma pack(1)`).

```perl
# C: #pragma pack(push, 1) ...
Packed[ 1, Struct[ flag => Char, data => Int ] ];
```

### `Array[ $type, $count ]`

A fixed-size C array. Maps to a Perl `ArrayRef`.

```perl
# C: double Vector3[3];
typedef Vector3 => Array[ Double, 3 ];
```

### Bitfields

Specify bit widths using the pipe (`|`) operator within Structs/Unions. Affix handles all masking and shifting.

```perl
# C: typedef struct { uint32_t a : 1; uint32_t b : 3; } Config;
typedef Config => Struct[ a => UInt32 | 1, b => UInt32 | 3 ];
```

## Live Views (Zero-Copy Aggregates)

Standard structs and arrays copy data between Perl and C. Live views allow you to directly manipulate C memory through
Perl references.

`Live[ $type ]` Returns a live, zero-copy view of the memory as defined by `$type`.

If `$type` is a `Struct` or `Union`, it returns an `Affix::Live` tied hash. Modifying keys in this hash updates C
memory immediately.

If `$type` is an `Array`, it returns an `Affix::Pointer` object. Modifying elements (e.g. `$arr->[0] = 5`)
writes directly to memory.

```perl
# Example: Live view of a struct
my $live = cast( $ptr, Live[ Struct[ x => Int, y => Int ] ] );
$live->{x} = 42; # Updates C memory
```

### Unified Access

`Affix::Pointer` objects for aggregates allow direct field access (`$p->{field}`) without explicit casting.

```perl
affix $lib, 'get_ptr', [] => Pointer[Point];
my $p = get_ptr();
say $p->{x};  # Unified access! Reads directly from C memory.
$p->{y} = 50; # Writes directly to C memory.
```

## Callbacks & Functions

- **`Callback[ [$params] => $ret ]`**: Defines the signature of a C function pointer. Allows you to pass Perl subroutines into C functions.

    ```perl
    # C: void set_handler( void (*cb)(int) );
    affix $lib, 'set_handler', [ Callback[ [Int] => Void ] ] => Void;
    ```

- **`ThisCall( $cb_or_sig )`**: Helper for C++-style `__thiscall` callbacks. Prepends a `Pointer[Void]` (the `this` pointer) to the signature.

README.md  view on Meta::CPAN

attempts to guess the correct C type for Perl scalars, these guesses might not always match the library's expectations
like passing a 64-bit integer where a 32-bit one is expected, or a float instead of a double.

Use `coerce( $type, $value )` to explicitly tell Affix how to marshal a variadic argument.

```perl
# Suppose we have a variadic log function that expects specific bit-widths
# C: void custom_log(int level, ...);
affix $lib, 'custom_log', [ Int, VarArgs ] => Void;

custom_log(
    1,
    coerce(Short, 10),    # Explicitly pass as a 16-bit signed int
    coerce(Float, 1.5),    # Explicitly pass as a 32-bit float
    coerce(ULong, 1000)    # Explicitly pass as a platform-native unsigned long
);
```

Note: Standard C default argument promotions still apply. For example, passing a `Float` to a variadic function will
typically be promoted to a `Double` by the C runtime unless the receiving function specifically handles raw floats.

## Enumerations

```perl
# C: enum Status { OK = 0, ERROR = 1, FLAG_A = 1<<0, FLAG_B = 1<<1 };
typedef Status => Enum[
    [ OK => 0 ],
    'ERROR',                    # Auto-increments to 1
    [ FLAG_A => 1 << 0 ],       # Bit shifting
    [ FLAG_B => '1 << 1' ]      # String expression
];
```

- **Constants:** `typedef` installs constants (e.g., `OK() == 0`) into your package.
- **Dualvars:** Values returned from C act as dualvars. They print as strings (`"OK"`) but evaluate mathematically as integers (`0`).
- **String Marshalling:** You can pass the string name of an element (`"OK"`) directly to functions that expect
that enum type.
- **Aliases:** You can also use `IntEnum[ ... ]`, `CharEnum[ ... ]`, and `UIntEnum[ ... ]` to force the underlying integer size.

## SIMD Vectors

Vectors are first-class types. You can interact with them using standard **ArrayRefs** (convenient) or **Packed Strings**
(high-performance, zero-overhead).

- **`Vector[ $size, $type ]`**: Create a custom vector (e.g., `Vector[ 4, Float ]`).
- **Aliases**: `M256`, `M256d`, `M512`, `M512d`, `M512i`.

```perl
# C: __m256 add_vecs(__m256 a, __m256 b);
affix $lib, 'add_vecs', [ M256, M256 ] => M256;
my $v1 = pack('f8', 1..8);
my $v2 = pack('f8', 10, 20, 30, 40, 50, 60, 70, 80);
my $packed_res = add_vecs( $v1, $v2 );
```

# MEMORY MANAGEMENT

When bridging Perl and C, handling raw memory safely is critical. Affix uses **Pins** to manage this boundary.

A Pin (an `Affix::Pointer` object) is a magical scalar reference that holds a C memory address, its associated type
information, and an ownership flag. If a Pin is "managed", Perl will automatically free the underlying memory when the
variable goes out of scope.

## Allocation & Deallocation

These functions allocate memory on the C heap. Memory allocated via these functions is **managed by Perl** by default.

### `malloc( $size )`

Allocates `$size` bytes of uninitialized memory. Returns a managed `Pointer[Void]` pin.

```perl
my $ptr = malloc(1024); # Allocates 1KB
# $ptr is automatically freed when it goes out of scope
```

### `calloc( $count, $type )`

Allocates memory for an array of `$count` elements of the given `$type`, and zero-initializes the memory. Returns a
managed pin typed as an Array.

```perl
my $arr = calloc( 10, Int );
$arr->[0] = 42; # Write directly to the first element
```

### `realloc( $ptr, $new_size )`

Resizes the memory area pointed to by `$ptr` to `$new_size` bytes. The original pin is updated automatically
in-place.

```
$ptr = realloc( $ptr, 2048 );
```

### `strdup( $string )`

Allocates managed memory and copies the Perl string (along with a `NULL` terminator) into it. Returns a managed
`Pointer[Char]` pin.

```perl
my $str_ptr = strdup("Hello C!");
```

### `free( $ptr )`

Manually releases memory.

**Warning:** Only use this on memory that you exclusively own (e.g., allocated via `malloc`). Do not call `free` on
unmanaged pointers returned by C libraries unless the library explicitly transfers ownership to you, or you will cause
a segmentation fault.

```
free($ptr);
```

## Lifecycle & Ownership

### `own( $ptr, [$bool] )`

Gets or sets the lifecycle management status of a pointer.

README.md  view on Meta::CPAN

- **Windows (Microsoft x64):** Arguments are passed in `rcx, rdx, r8, r9`, with "shadow space" reserved on the stack.

## Go

Go libraries can be loaded if they are compiled with `-buildmode=c-shared`. Note that Go slices and strings contain
internal metadata (length/capacity) and do not map directly to C arrays or `char*`. Use the `C` package inside Go
(`import "C"`) and `*C.char` to bridge the boundary.

# ERROR HANDLING & DEBUGGING

Bridging two entirely different runtimes can lead to spectacular crashes if types or memory boundaries are mismatched.
Affix provides built-in tools to help you identify what went wrong.

## Error Handling

### `errno()`

Accesses the system error code from the most recent FFI or standard library call (reads `errno` on Unix and
`GetLastError` on Windows).

This function returns a **dualvar**. It behaves as an integer in numeric context, and magically resolves to the
human-readable system error message (via `strerror` or `FormatMessage`) in string context.

```perl
# Suppose a C file-open function fails
my $fd = c_open("/does/not/exist");
if (!$fd) {
    my $err = errno();

    # String context
    say "Failed to open: $err"; # "No such file or directory"

    # Numeric context
    if (int($err) == 2) {
        say "Code 2 specifically triggered.";
    }
}
```

**Note:** You must call `errno()` immediately after the C function invokes, as subsequent Perl operations (like
printing to STDOUT) might overwrite the system's error register.

## Memory Inspection

### `dump( $pin, $length_in_bytes )`

Prints a formatted hex dump of the memory pointed to by a Pin directly to `STDOUT`. This is an invaluable tool for
verifying that C structs or buffers contain the data you expect.

```perl
my $ptr = strdup("Affix Debugging");
dump($ptr, 16);

# Output:
# Dumping 16 bytes from 0x55E9A8A5 at script.pl line 42
#  000  41 66 66 69 78 20 44 65 62 75 67 67 69 6e 67 00 | Affix Debugging.
```

### `sv_dump( $scalar )`

Dumps Perl's internal interpreter structure (SV) for a given scalar to `STDOUT`. This exposes the raw flags, reference
counts, and memory layout of the Perl variable itself.

```perl
my $val = 42;
sv_dump($val);
# Exposes IV flags, memory addresses of the SV head, etc.
```

## Advanced Debugging

### `set_destruct_level( $level )`

Sets the internal `PL_perl_destruct_level` variable.

When testing XS/FFI code for memory leaks using tools like Valgrind or AddressSanitizer, you often want Perl to
meticulously clean up all global memory during its destruction phase (otherwise the leak checker will be flooded with
false-positive "leaks" that are actually just memory Perl intentionally leaves to the OS to reclaim).

```
# Call this at the start of your script when running under Valgrind
set_destruct_level(2);
```

# COMPANION MODULES

Affix ships with two powerful companion modules to streamline your FFI development:

- [**Affix::Wrap**](https://metacpan.org/pod/Affix%3A%3AWrap): Parses C/C++ headers using the Clang AST to automatically generate Affix bindings for entire libraries.
- [**Affix::Build**](https://metacpan.org/pod/Affix%3A%3ABuild): A polyglot builder that compiles inline C, C++, Rust, Zig, Go, and 15+ other languages into dynamic libraries you can bind instantly.

# THREAD SAFETY & CONCURRENCY

Affix bridges Perl (a single-threaded interpreter, generally) with libraries that may be multi-threaded. This creates
potential hazards that you must manage.

## 1. Initialization Phase vs. Execution Phase

Functions that modify Affix's global state are **not thread-safe**. You must perform all definitions in the main thread
before starting any background threads or loops in the library.

Unsafe operations that you should never call from Callbacks or in a threaded context:

- `affix( ... )` - Binding new functions.
- `typedef( ... )` - Registering new types.

## 2. Callbacks

When passing a Perl subroutine as a `Callback`, avoid performing complex Perl operations like loading modules or
defining subs inside callbacks triggered on a foreign thread. Such callbacks should remain simple: process data, update
a shared variable, and return.

If the library executes the callback from a background thread (e.g., window managers, audio callbacks), Affix attempts
to attach a temporary Perl context to that thread. This should be sufficient but Perl is gonna be Perl.

# RECIPES & EXAMPLES

See [The Affix Cookbook](https://github.com/sanko/Affix.pm/discussions/categories/recipes) for comprehensive guides to
using Affix.

## Linked List Implementation

```perl
# C equivalent:
# typedef struct Node {
#     int value;
#     struct Node* next;



( run in 1.659 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )