Developer guide
Developer guide for ENCY plugins (CAMAPI) and external applications (CAMIPC): concepts, domain reference with C# examples, and macros. Full example projects are in the cam-api-examples repository.
Start here
What are you building?
| Task | Where to start |
|---|---|
| In-process plugin (DLL loaded by ENCY) | CAMAPI overview → Entry points guide |
| Standalone external app communicating with ENCY | CAMIPC overview → IPC connection guide |
| Not sure which API to use | See comparison below |
ENCY shows an error or crashes when closing after my plugin ran — undestroyed-objects dialog, LostObjects_*.txt, AV on exit |
COM lifetime → Symptoms — almost always a missing using |
CAMAPI vs CAMIPC
| CAMAPI | CAMIPC | |
|---|---|---|
| Deployment | DLL plugin, loaded by ENCY | Standalone .exe, connects via IPC |
| Trigger | User clicks button / lifecycle event | Initiated by external app |
| Performance | In-process, direct COM calls | IPC overhead per call |
| Typical use | Custom operations, UI extensions, solvers | Automation, integration, testing |
| Entry point | IExtension* interfaces |
IIpcHelper → ICamIpcApplication |
Documentation map
Concepts (read these first)
- Extension entry points — all 7 plugin types, when to use each, full C# boilerplate
- COM lifetime management — ComWrapper, Invoke vs InvokeAndWrap, ListComWrapper, MTA, event-handler arguments, and what a forgotten
usinglooks like at application shutdown - Error handling — TResultStatus, no-exceptions rule, IExtensionLogger
- UI patterns — Inspector dialog, modal WPF (STA thread), non-modal WPF + IExtensionLazyUnloadable
- Theming plugin windows — applying the host palette to your own window; WinForms visual-styles pitfalls, scrollbars, title bar
Writing macros
- Macros — authoring a macro body (
ICamApiMacro.Run, run context,MacroParams,NotifyMacroStep). Managing/building/running macros from a host is in api/application.md (in-process) and ipc/application.md (IPC).
CAMAPI domain reference
- Application & singletons — ICamApiApplication, utilities, macros, events, collections
- Entry points — IExtensionManager, IExtensionStorage, IExtensionLogger
- Project — ICamApiProject, technologist, tech operations, parts, stages, snapshots
- Geometry — model tree, entities, faces, curves, mesh, coordinate systems, GeomPicker, sketcher, point snapper
- CAD — CAD modelling: sketches, extrude, revolve, cut / union / intersect, fillet, chamfer, draft, bodies
- Feature finder — automatic recognition of holes, pockets, fillets, chamfers, planes, edges
- Tools & machine — machining tools, tool lists, machines, workpiece setup, live machine state
- NC & simulation — NCMaker, Simulator, CLDReceiver, ModelFormer, TechOperationSolver
- UI — main form, viewport, view cube, dialogs, SimplePropIterator, CamApiInspectorWindow
CAMIPC domain reference
- Connection — DLL loading, IIpcHelper, TExecuteContext, IAsyncResult, event listeners
- Application — ICamIpcApplication, paths, extension manager, logger, XmlProp
- Project — differences from CAMAPI project domain
- Geometry — differences from CAMAPI geometry domain
- CAD — differences from CAMAPI CAD domain
- Feature finder — differences from CAMAPI feature-finder domain
- Tools & machine — differences from CAMAPI tools domain
- NC & simulation — differences from CAMAPI NC domain
- UI — main form, viewport, view cube, PrimeView, PrimeViewModel
- Extra — CloudsApp, FunctionalTest, Extension.PLM
- Macros — record & save over IPC — MacroManager → builder → commands, recording lifecycle, command schema, guard cases
Key patterns (quick reference)
Minimal CAMAPI plugin
// 1. Implement IExtension + chosen entry point interface
public class MyPlugin : IExtension, IExtensionUtility {
public IExtensionInfo? Info { get; set; }
public void Run(IExtensionUtilityContext context, out TResultStatus resultStatus) {
resultStatus = default;
try {
using var appCom = ComWrapper.Create(context.CamApplication);
using var projectCom = appCom.GetActiveProject();
// your logic here
} catch (Exception e) {
resultStatus.Code = TResultStatusCode.rsError;
resultStatus.Description = e.Message;
}
}
}
// 2. Register in extension.json (see general/extension-entry-points.md for full format)
Minimal CAMIPC connection
// Load helper DLL and connect (see ipc/connection.md for full details)
var helper = IpcHelperLoader.Load("CAMIPC.Helper.Cam.dll");
var context = new TExecuteContext { Timeout = 5000 };
using var appCom = helper.ConnectToRunningInstance(context);
COM lifetime rule
// Always use 'using' — never store COM objects in fields without explicit lifetime control
using var projectCom = appCom.GetActiveProject(); // correct
var project = appCom.GetActiveProject(); // WRONG — leaks COM reference
ComWrapper<T> has no finalizer: an undisposed wrapper is never released, and the host reports it (or crashes) when ENCY closes — see Symptoms.