Processes, callbacks and ownership
An EpicTuner plugin is a native library loaded into its own worker process. The application owns ECU communication, calibration validation, licensing and the panels rendered with EpicTuner controls.
The path of a request
Your C++ plugin
↓ C++ helpers / C ABI service tables
Plugin worker (one process per enabled plugin)
↓ bounded authenticated local messages
EpicTuner broker
↓ GUI models, read adapters, edit validation, settings and licensing
Application and its existing ECU communication worker
The function pointers and C++ objects remain inside the worker. IPC carries bounded values and IDs, never pointers or raw C structure images. Each panel from a plugin shares that plugin's worker. Worker process separation contains crashes; it is not an OS security sandbox. A native library still has the current user account's file and network access.
Lifecycle
The host discovers and verifies a package, checks compatibility, then starts an
enabled plugin. The worker negotiates et_plugin_query and calls start.
Lifecycle, UI and read callbacks are serialized on its dispatcher. A plugin that
starts successfully becomes ready.
Disable, update and exit drain or cancel owned work before stop destroys the
instance. The host replaces the worker process for updates. It does not unload a
library with live callbacks. A crash or missed heartbeat changes the plugin to a
visible failure state, revokes subscriptions and disables its controls.
Restart is explicit; it never replays prior actions or tune writes.
Threading
Call host services from the worker dispatcher. Use jobs for expensive CPU work. A job receives copied inputs and a cancellation token, computes a bounded result, and returns through a dispatcher completion. Do not call UI, logging or read services from the job thread.
Never block a callback waiting for a dialog, request or job to finish. Deliver the next step from its completion callback. The application GUI never waits synchronously for plugin code.
Data lifetimes
| Value | Lifetime |
|---|---|
| Request strings, nodes, channel arrays | Copied during the service call |
| Event/reply strings and arrays | Borrowed until the callback returns |
| Callback owner | Must remain alive until cancellation/completion has drained |
| Panel/subscription/proposal handle | Scoped to its worker session and relevant project generation |
| C++ object or allocation | Created and destroyed in its own module |
Copy a borrowed log batch before passing it to a background task. Treat handles as opaque tokens. A project close or replacement invalidates generation-bound work even if the newly opened project has the same name or path.
Error handling
Service calls can fail immediately without queuing a callback. Otherwise the terminal callback reports success, cancellation or rejection. A timeout does not prove that a calibration commit failed; consult host status and read back the current tune before proposing another edit.
The C++ adapters catch callback exceptions inside the module and translate them
to ET_ERROR_CALLBACK. C authors must provide the same no-exception boundary.
See foundation, API reference and
troubleshooting for exact contracts.