Overview
Unlike traditional Pure Data where externals are loaded as shared libraries, plugdata statically compiles externals into the application. This ensures:- ✅ Externals work in plugin hosts (DAWs)
- ✅ No external file dependencies
- ✅ Consistent behavior across platforms
- ✅ Better performance and security
Quick Start
add_library(externals STATIC
${ELSE_SOURCES}
${CYCLONE_SOURCES}
${PDLUA_SOURCES}
# Add your external here:
path/to/your/external.c
)
void Setup::initialiseELSE()
{
// ... existing setup calls ...
myexternal_setup(); // Add your setup call
// ... more setup calls ...
}
Setup Function Locations
Choose where to call your setup function based on desired namespace:libpd_init_pdlua (Recommended)
Called inSetup::initialisePdLua() (Source/Pd/Setup.cpp:1399-1402).
Best for:
- Standalone externals
- No namespace prefix required
- Independent objects
initialiseELSE
Called inSetup::initialiseELSE() (Source/Pd/Setup.cpp:1473).
Note:
Example:
initialiseCyclone
Similar to ELSE, but for Cyclone compatibility. Note: Externals available as[myexternal] and [cyclone/myexternal].
Complete Example
Let’s add a simple gain external:#include "m_pd.h"
static t_class *mygain_tilde_class;
typedef struct _mygain_tilde {
t_object x_obj;
t_float x_gain;
t_float x_f; // dummy float for signal inlet
} t_mygain_tilde;
t_int *mygain_tilde_perform(t_int *w)
{
t_mygain_tilde *x = (t_mygain_tilde *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int n = (int)(w[4]);
t_float gain = x->x_gain;
while (n--)
*out++ = *in++ * gain;
return (w+5);
}
void mygain_tilde_dsp(t_mygain_tilde *x, t_signal **sp)
{
dsp_add(mygain_tilde_perform, 4, x,
sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
void mygain_tilde_float(t_mygain_tilde *x, t_float f)
{
x->x_gain = f;
}
void *mygain_tilde_new(t_floatarg f)
{
t_mygain_tilde *x = (t_mygain_tilde *)pd_new(mygain_tilde_class);
x->x_gain = f;
outlet_new(&x->x_obj, &s_signal);
return (x);
}
void mygain_tilde_setup(void)
{
mygain_tilde_class = class_new(gensym("mygain~"),
(t_newmethod)mygain_tilde_new, 0,
sizeof(t_mygain_tilde),
CLASS_DEFAULT,
A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(mygain_tilde_class, t_mygain_tilde, x_f);
class_addmethod(mygain_tilde_class, (t_method)mygain_tilde_dsp,
gensym("dsp"), A_CANT, 0);
class_addfloat(mygain_tilde_class, mygain_tilde_float);
}
void Setup::initialiseELSE()
{
pdlink_setup();
pdlink_tilde_setup();
// Add after other setup calls:
mygain_tilde_setup();
knob_setup();
above_tilde_setup();
// ... rest of ELSE externals ...
}
Multi-File Externals
For externals with multiple source files:Libraries/CMakeLists.txt
Including Headers
For externals needing additional headers:Libraries/CMakeLists.txt
Platform-Specific Code
Use preprocessor directives for platform-specific code:Common Issues
Undefined Reference Errors
extern "C" block and definition matches exactly.
External Not Found
Multiple Definition Errors
Code References
Key files for adding externals:- External targets: Libraries/CMakeLists.txt:453-454
- ELSE auto-compilation: Libraries/CMakeLists.txt:215-241
- Setup declarations: Source/Pd/Setup.cpp:159-1321
- initialiseELSE: Source/Pd/Setup.cpp:1473-1829
- initialisePdLua: Source/Pd/Setup.cpp:1399-1402
Next Steps
Building from Source
Learn the complete build process
Lua Scripting
Create externals using Lua scripting
