Affix

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN


- **`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[ $aggregate ]` / `Packed[ $align, $aggregate ]`

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

```perl
# Without explicit alignment (default):
Packed[ Struct[ flag => Char, data => Int ] ];

# With explicit alignment (e.g., #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)

In Affix, memory structures are live by design. When C returns a pointer to an aggregate (Struct, Union, or Array), or
when you use `cast()` to overlay a type onto a memory address, Affix does not copy the data.

Instead, it returns a magical Perl reference (blessed into `Affix::Pointer`) mapped directly to the C memory via Perl
VTables. This means zero-copy performance without the overhead of `tie`.

Modifying keys or elements in these structures updates C memory immediately, and reading them reads directly from the C
heap.

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

### Unified Access

Magical `Affix::Pointer` references 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.

## Variadic Functions (VarArgs)

Affix supports C functions that take a variable number of arguments (e.g., `printf`, `ioctl`). When defining a
signature, use the `VarArgs` token at the end of the argument list.

### Basic Usage

```perl
# C: int printf(const char* format, ...);
affix libc(), ['printf' => 'my_printf'], [ String, VarArgs ] => Int;

# Basic types are marshalled automatically based on Perl's internal state
my_printf("Integer: %d, String: %s\n", 42, "Hello");
```

### Explicit Type Control with `coerce()`

In variadic functions, C relies on the caller to pass data in the exact format the function expects. While Affix
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;



( run in 1.276 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )