aligned_array.py

download raw

# SPDX-FileCopyrightText: 2026 Jeff Epler
#
# SPDX-License-Identifier: CC0-1.0

import ctypes

_alignment_ever_failed = set()
def aligned_array(object_type, alignment=None):
    """Create an aligned array.

    Return an array with `count` elements of type `element_type`.
    The first element is aligned to a multiple of `alignment`, or
    the size of `element_type` if `alignment` is unspecified.
    """

    alignment = alignment or ctypes.alignment(object_type)
    mask = alignment - 1
    if alignment & mask:
        raise ValueError("Alignment must be a power of two")

    object_size = ctypes.sizeof(object_type)
    if alignment not in _alignment_ever_failed:
        obj = object_type()
        if ctypes.addressof(obj) & mask == 0:
            return obj
        _alignment_ever_failed.add(alignment)
        del obj

    alloc_size = object_size + mask
    buffer = (ctypes.c_uint8 * alloc_size)()
    misalignment = (alignment - ctypes.addressof(buffer)) & mask
    result = object_type.from_buffer(
            memoryview(buffer)[misalignment:misalignment+object_size]
            )
    assert ctypes.addressof(result) & mask == 0
    return result

if __name__ == '__main__':
    arrays1 = [(ctypes.c_uint8 * 4)() for _ in range(16)]
    arrays2 = [aligned_array(ctypes.c_uint8 * 4, 16) for _ in range(16)]
    arrays3 = [aligned_array(ctypes.c_uint8 * 4, 256) for _ in range(16)]

    print("unaligned")
    for a in arrays1: print(f"0x...{ctypes.addressof(a) & 0xff:02x}")
    print()

    print("16-aligned")
    for a in arrays2: print(f"0x...{ctypes.addressof(a) & 0xff:02x}")
    print()

    print("256-aligned")
    for a in arrays3: print(f"0x...{ctypes.addressof(a) & 0xff:02x}")

    print(f"{_alignment_ever_failed=}")