v0.5.4
Extension composition, reworked
This release matures the runtime composition introduced in v0.5.3 into a trait +
attribute model and adds a CLI for it.
Entity model: pure C-function surface
Generated entities now carry only the methods named after C functions. The
method group lives in a generated <Class>LibraryComponent trait the entity mixes
in; all runtime machinery (booting, the loaded library, dispatch) moved to
Pnlx\FFI\NativeLibraryRegistry, and install-time metadata moved from constants to
a #[\Pnlx\Attribute\NativeLibrary] attribute. The only inherited surface is the two
magic methods (__construct, __callStatic), which a C function can never be named —
so composing several Components can only ever clash on real C-function names.
Compose into one shared FFI scope
A composed class mixes in several Components and shares ONE FFI scope, so a CData
returned by one library (e.g. an SDL2_image surface from IMG_Load) flows straight
into another (SDL_CreateTextureFromSurface):
Pnlx\Runtime::compose([A::class, B::class])— runtime: returns a class with
real methods, so by-reference out-parameters round-trip ($x->SDL_QueryTexture($t, $w, $h)).pnl compose <a> <b> --as <Class> [--prefix <p>]— generates a NAMED composite
class file (for editor/static-analysis support), recorded inpnl.jsoncomposites
and wired into the autoload.--prefixresolves method-name collisions via trait
insteadof/as. You can also hand-writenew class extends AbstractExtension { use ACompoent; use BComponent; }— composition needs no special runtime call.
Boot shares the one scope with each member entity, so a pointer wrapped/allocated via
a member's type class is usable by the composite.
use_functions
With features.use_functions, pnl compose also emits composite global functions
under \Pnlx\Func\<Class>\* that delegate to the composite class (sharing its scope;
by-reference out-parameters preserved), retargeted from each member's own
functions.php with --prefix applied to collisions.
Other
- New
compositessection inpnl.json(schemapnl/2026-07-01). build.rsnow fingerprintsschemas/(as it already didsrc/sdk) so a schema
edit always re-embeds into the support library — the runtime no longer validates
against a stale schema.
NOTE: composing two libraries that export the same C symbol shares one global
symbol (the first loaded wins); pnl compose --prefix de-conflicts the PHP names but
warns about this.