Skip to content

pd: register the class under the external's own name (fixes Pd recursion / can't-instantiate)#168

Merged
jcelerier merged 3 commits into
mainfrom
fix-pd-class-name
Jul 9, 2026
Merged

pd: register the class under the external's own name (fixes Pd recursion / can't-instantiate)#168
jcelerier merged 3 commits into
mainfrom
fix-pd-class-name

Conversation

@jcelerier

Copy link
Copy Markdown
Member

Symptom

In Pure Data, most objects of an addon like score-addon-puara can't be
instantiated — Pd aborts with its abstraction recursion limit.

Root cause

Pd loads a single-object external by filename and requires the registered
class symbol to equal that filename. avendish names the file and the setup
function after the CMake C_NAME (<C_NAME>.pd_*, <C_NAME>_setup), but the Pd
binding registered the class under symbol_from_name<T>() — the introspected
C++ symbol/identifier (get_static_symbol), not C_NAME.

When they differ — e.g. puara ships C_NAME smoother for a struct Smoother, or
any struct without a c_name meta (so get_c_name/get_static_symbol fall back
to the identifier) — Pd loads smoother.pd_linux, runs smoother_setup, but the
class it registers is Smoother. Pd never finds smoother, retries via the
loader, and eventually hits the recursion limit. (Max has the same class:
class_new(get_c_name<T>()) — see follow-ups.)

Fix

Thread @AVND_C_NAME@ from the setup function into the audio/message metaclass so
class_new() uses the external's own name. Falls back to the introspected name
when the metaclass is constructed directly (tests), so nothing else changes.

Validation

An addon with C_NAME coolthing / struct Foo (no c_name meta) now generates
coolthing_setup()class_new(gensym("coolthing")) and builds a coolthing.*
external. Before, it registered class Foo and [coolthing] could not be created.

Follow-ups (not in this PR)

  1. Max: class_new(get_c_name<T>()) has the same flaw — it should use
    @AVND_C_NAME@ too, or it breaks whenever C_NAME != get_c_name.
  2. Help/example patches: generated from the dump JSON's c_name
    (= get_c_name<T>), so they still reference the introspected name rather than
    the shipped C_NAME. Making the dump's c_name authoritative (@AVND_C_NAME@)
    would fix the demo object box in every backend's help patch.

🤖 Generated with Claude Code

https://claude.ai/code/session_014Z4KK2Rays9dTj8J2AJcFZ

Pd finds a single-object external by filename and requires the registered class
symbol to equal that filename. avendish names the file and the setup function
after the CMake C_NAME (@AVND_C_NAME@.pd_*, @AVND_C_NAME@_setup), but the class
was registered under symbol_from_name<T>() = the introspected C++ symbol/
identifier. When those differ (e.g. an addon whose C_NAME is 'smoother' but whose
struct is 'Smoother', or any object without a c_name meta), Pd loads the file,
runs setup, but the class it asked for is never registered -- so its loader
retries and eventually aborts with the abstraction recursion limit. This made
most puara objects impossible to instantiate.

Thread @AVND_C_NAME@ from the setup function into the audio/message metaclass so
class_new() uses exactly the external's name (falling back to the old introspected
name when the metaclass is constructed directly, e.g. in tests).

Verified: an addon with C_NAME 'coolthing' and struct 'Foo' (no c_name meta) now
emits coolthing_setup() -> class_new(gensym("coolthing")) and builds a
coolthing.\* external; previously it registered class 'Foo' and could not be created.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Z4KK2Rays9dTj8J2AJcFZ
@jcelerier
jcelerier force-pushed the fix-pd-class-name branch from 2e639eb to 7f74ad1 Compare July 9, 2026 19:40
jcelerier and others added 2 commits July 9, 2026 16:16
Every object is built for the golden differential harness (SDK-free, always on),
so one static_assert there enforces the name invariant for all back-ends at once,
rather than duplicating it per shipping backend: when an object declares an
explicit halp_meta(c_name, ...), the avnd_addon_object / avnd_make_* C_NAME must
equal it (they name the same external -- the file + class Pd/Max load by). Objects
that declare no c_name leave the CMake C_NAME authoritative. Verified across all
224 golden objects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Z4KK2Rays9dTj8J2AJcFZ
The object declares c_name() == "avnd_sampleaccurate" but was built as C_NAME
avnd_sample_accurate_controls, which the golden static_assert rejects. Use the
object's declared name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Z4KK2Rays9dTj8J2AJcFZ
@jcelerier
jcelerier force-pushed the fix-pd-class-name branch from 17db40d to 66eff6a Compare July 9, 2026 20:17
@jcelerier
jcelerier merged commit 4807598 into main Jul 9, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant