Build cleanup, pathname reorganisation, cdef to repository (although generated with gen_cdef.py).

This commit is contained in:
Leo Vasanko
2025-11-06 15:23:30 -06:00
parent c8fe16d21f
commit d43a22bc6c
14 changed files with 805 additions and 292 deletions
+10 -64
View File
@@ -1,33 +1,13 @@
"""Dynamic loader for libaegis using CFFI (ABI mode).
This module loads the shared library bundled with the package.
Exports:
- ffi: a cffi.FFI instance with the libaegis API declared
- lib: the loaded libaegis shared library (ffi.dlopen)
- libc: the C runtime (for posix_memalign/free on POSIX)
- alloc_aligned(size, alignment): return (void*) pointer with requested alignment
"""
"""Dynamic loader for libaegis using CFFI (ABI mode)."""
import os
import sys
from pathlib import Path
from typing import Any
from cffi import FFI
ffi = FFI()
# Load CFFI cdef declarations from text file
cdef_path = os.path.join(os.path.dirname(__file__), "build", "aegis_cdef.h")
with open(cdef_path, "r", encoding="utf-8") as f:
cdef_content = f.read()
ffi.cdef(cdef_content)
try:
# ctypes is only used to resolve libc reliably across platforms
import ctypes.util as _ctypes_util # type: ignore
except Exception: # pragma: no cover - very unlikely to happen
_ctypes_util = None # type: ignore[assignment]
__ALL__ = ["ffi", "lib"]
def _platform_lib_name() -> str:
@@ -39,52 +19,18 @@ def _platform_lib_name() -> str:
def _load_libaegis():
pkg_dir = os.path.dirname(__file__)
candidate = os.path.join(pkg_dir, "build", _platform_lib_name())
if os.path.exists(candidate):
pkg_dir = Path(__file__).parent
candidate = pkg_dir / "build" / _platform_lib_name()
if candidate.exists():
try:
return ffi.dlopen(candidate)
return ffi.dlopen(str(candidate))
except Exception as e:
raise OSError(f"Failed to load libaegis from {candidate}: {e}")
else:
raise OSError(f"Could not find libaegis at {candidate}")
def _load_libc():
# Use ctypes.util to find a usable libc name; fallback to None-dlopen on POSIX
if _ctypes_util is not None:
libc_name = _ctypes_util.find_library("c") # type: ignore[attr-defined]
if libc_name:
try:
return ffi.dlopen(libc_name)
except Exception:
pass
# Fallback: try process globals (works on many Unix platforms)
try:
return ffi.dlopen(None)
except Exception as e:
raise OSError(f"Unable to load libc for aligned allocation: {e}")
ffi = FFI()
ffi.cdef(Path(__file__).with_name("aegis_cdef.h").read_text(encoding="utf-8"))
lib: Any = _load_libaegis()
libc: Any = _load_libc()
# Initialize CPU feature selection (recommended by the library)
try:
lib.aegis_init()
except Exception:
# Non-fatal; functions will still work, maybe slower
pass
def alloc_aligned(size: int, alignment: int = 64):
"""Allocate aligned memory via posix_memalign(); returns a void* cdata.
The returned pointer must be freed with libc.free(). Attach a GC finalizer
at call sites using ffi.gc(ptr, libc.free) after casting to the target type.
"""
memptr = ffi.new("void **")
rc = libc.posix_memalign(memptr, alignment, size)
if rc != 0 or memptr[0] == ffi.NULL:
raise MemoryError(f"posix_memalign({alignment}, {size}) failed with rc={rc}")
return memptr[0]
lib.aegis_init()