Fusion Guide
advanced8 min read

C++ API Notes

When to choose the Fusion C++ API over Python, how the generated project is organised, core idioms such as Ptr<T>, and build, debug and deployment notes.

Overview#

The Fusion API is available in Python, C++ and (experimental) TypeScript. Autodesk describes it as "a single API", so the languages expose the same object model (Application, Design, Component, Sketch, and the rest) and the same events, with "small language specific syntax changes". The difference lies in everything around the API: how you build, how you debug, how you deliver, and how fast the surrounding code runs.

Most users should start in Python. This page explains when C++ becomes the better tool, how a C++ add-in is structured, the language idioms you must learn (smart pointers, handler classes, error handling), and how to build and deploy. It is deliberately a set of notes rather than a full tutorial: the C++ toolchain details differ by operating system and Fusion release, so verify steps against the generated template in your installed version.

Where to find it#

  • In the Scripts and Add-Ins dialog, the Create dialog offers C++ as a language. Choosing it creates a single .cpp file plus both a Visual Studio (.vcxproj) and an Xcode (.xcodeproj) project that use it. The same source usually works on both systems, but the binary is OS specific: compile on Windows with Visual Studio and on Mac with Xcode.
  • One header per class is installed with Fusion in the .../API/CPP/include folder, under top-level Core and Fusion folders. Each class, method, property and event topic in the reference names the header to include.
  • Most code samples in the reference have Python, C++ and TypeScript tabs.

When to choose C++#

ReasonWhy C++ helpsCaveat
Performance in tight loopsNative speed for geometry processing, mesh handling, evaluatorsAPI calls themselves cost the same; only your own code speeds up
Existing C++ librariesLink CGAL, OpenCASCADE, Eigen, a vendor SDKBinary compatibility with Fusion's runtime must be checked
Closed-source distributionShip a compiled binaryReverse engineering is still possible
Strong typingCompile-time checks on large projectsMore boilerplate
Reusing code across productsShare modelling logic with another appFusion-specific code stays separate

Choose Python when: you want fast iteration, a gentle learning curve, use of Python packages, easy distribution (just text files), or need palettes with simple glue code. Python add-ins are what the bulk of public samples use.

A hybrid is common: a Python add-in for UI and orchestration that loads a compiled native extension for the heavy algorithm, using ctypes or a compiled Python module. The compatibility of such modules with Fusion's bundled Python version is your responsibility.

Anatomy of a C++ add-in#

A C++ add-in is a shared library (a DLL on Windows, a dylib on macOS) loaded by Fusion. It exports two functions, the C++ equivalent of Python's run and stop:

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>

using namespace adsk::core;
using namespace adsk::fusion;

Ptr<Application> app;
Ptr<UserInterface> ui;

extern "C" XI_EXPORT bool run(const char* context)
{
    app = Application::get();
    if (!app)
        return false;

    ui = app->userInterface();
    if (!ui)
        return false;

    ui->messageBox("Hello from C++");
    return true;
}

extern "C" XI_EXPORT bool stop(const char* context)
{
    if (ui)
    {
        ui->messageBox("Goodbye");
        ui.reset();
    }
    return true;
}

Observations:

  • Core/CoreAll.h and Fusion/FusionAll.h include every header (longer compile, same run time, per Autodesk); CAM/CAMAll.h appears in the CAM samples. The alternative is one include per class, such as <Core/Application/Application.h> and <Fusion/Fusion/Design.h>.
  • Namespaces mirror the Python modules: adsk::core, adsk::fusion, adsk::cam.
  • XI_EXPORT is the export macro used in Autodesk's samples (extern "C" XI_EXPORT bool run(const char* context)).
  • Methods that are properties in Python are functions in C++: app->userInterface() rather than app.userInterface. A setter is an overload that takes the value and returns a bool: comp->name("New Test").
  • The context is passed as a JSON string. A manifest file with "type": "addin" accompanies the library, plus sourcewindows and sourcemac keys naming the project files that Edit opens.

Idioms you must learn#

Ptr smart pointers#

All API objects are reference counted and wrapped in Ptr<T>. You never call new or delete on them. Copying a Ptr increments the count; letting it go out of scope decrements it. A null Ptr evaluates false:

Ptr<Product> product = app->activeProduct();
Ptr<Design> design = product;             // implicit downcast via assignment
if (!design)
    return false;                          // not a Design product
Ptr<Component> root = design->rootComponent();

Assigning a Ptr<Product> into a Ptr<Design> performs a checked cast and yields a null pointer when the types do not match (Autodesk: if the active product is CAM or Drawing, the variable is null). This is the equivalent of Design.cast(...) in Python. To test the exact type use obj->objectType() == adsk::fusion::SketchLine::classType(); if (Ptr<SketchCurve>(selectedEnt)) tests for any derived type. Compare two objects by comparing the Ptrs (face1 == face2).

Collections and iteration#

Ptr<Sketches> sketches = root->sketches();
for (size_t i = 0; i < sketches->count(); ++i)
{
    Ptr<Sketch> s = sketches->item(i);
    // ...
}

Indices are zero based. Autodesk's topic also shows range-based iteration: for (Ptr<BRepFace> f : body->faces()) { ... }.

Strings and numbers#

Strings in the API are std::string (the reference signatures use std::string; the topic does not state the encoding). Numbers are double; Design lengths are centimetres and angles are radians, exactly as in Python.

Input objects#

The same input-object pattern applies:

Ptr<Sketches> sketches = root->sketches();
Ptr<Sketch> sketch = sketches->add(root->xYConstructionPlane());
Ptr<SketchCircles> circles = sketch->sketchCurves()->sketchCircles();
circles->addByCenterRadius(Point3D::create(0, 0, 0), 2.0);

Ptr<ExtrudeFeatures> extrudes = root->features()->extrudeFeatures();
Ptr<Profile> prof = sketch->profiles()->item(0);
Ptr<ExtrudeFeatureInput> input =
    extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);
// setDistanceExtent is retired; use an extent definition (see the sketches page).
Ptr<DistanceExtentDefinition> extent =
    DistanceExtentDefinition::create(ValueInput::createByString("10 mm"));
input->setOneSideExtent(extent, ExtentDirections::PositiveExtentDirection);
extrudes->add(input);

Error handling#

In C++ "all errors are reported through error codes. There are not asserts fired so a try catch statement will not work." A function either returns the object or a documented failure value (usually null), or returns a bool. After a failing call, retrieve the message:

std::string errMsg;
int errCode = app->getLastError(&errMsg);
if (GenericErrors::Ok != errCode)
    ui->messageBox(errMsg);

Application::getLastError(std::string*) returns the error code for the most recent failure. Make a habit of checking each result before using it. (General guidance: dereferencing a null Ptr will crash.)

Event handlers#

Handlers derive from the C++ handler base classes and override notify:

class CommandCreatedHandler : public CommandCreatedEventHandler
{
public:
    void notify(const Ptr<CommandCreatedEventArgs>& eventArgs) override
    {
        Ptr<Command> cmd = eventArgs->command();
        if (!cmd) return;
        Ptr<CommandInputs> inputs = cmd->commandInputs();
        inputs->addStringValueInput("name", "Name", "Part");
        // add further inputs and execute handlers...
    }
};

static CommandCreatedHandler cmdCreatedHandler;   // static storage: lives as long as the DLL

Register with cmdDef->commandCreated()->add(&cmdCreatedHandler); (Autodesk's sample connects the event this way and keeps the handler as a member of a long-lived object). Keep handler objects alive for the whole lifetime of the registration, using static storage or members of a long-lived object. General guidance: in C++ a handler destroyed too early is likely to crash rather than fail silently.

Step by step: create and build a C++ add-in#

  1. Install a C++ toolchain: Visual Studio on Windows, or Xcode on macOS (Autodesk says you compile for Windows with Visual Studio and for Mac with Xcode).
  2. In Fusion, open Scripts and Add-Ins, click +, choose Create script or add-in, select C++ and Add-In, name it, and click Create.
  3. Open the generated project (the manifest's sourcewindows / sourcemac keys name the .vcxproj / .xcodeproj; Edit opens it with the application associated with that file type).
  4. Build the project; you must be able to compile successfully before debugging.
  5. Back in Fusion, select the add-in and run it. While developing, do not enable Run on Startup.
  6. To debug on Windows: add breakpoints, then in Visual Studio choose Debug > Attach to Process, set "Attach to" to Native code, pick Fusion360.exe, and click Attach (your breakpoints show as disabled until your code loads). Run the add-in from Scripts and Add-Ins; breakpoints in run are hit, and breakpoints in command code are hit when you click the command's button. On Mac, use Xcode's Debug > Attach to Process and select "Autodesk Fusion".
  7. To finish, stop the add-in in Scripts and Add-Ins and then stop debugging (Stop Debugging in Visual Studio, Detach in Xcode). If a compile error appears, the add-in is usually still running in Fusion; stop it first.

Options reference#

Setting / conceptWhat it doesNotes
run / stop exportsEntry pointsReturn bool, take a context string
Ptr<T>Reference-counted handleNever delete
app->getLastErrorFetch last error textCall right after failure
XI_EXPORTExport macroRequired on both entry points
Build configurationDebug or ReleaseRelease for distribution
ArchitectureNot stated in the documentation> Note: not confirmed: supported CPU architectures; match your Fusion install
Manifest typeaddinSame as Python
Runtime libraryMust match what the headers expectUse the template's settings; do not change

Packaging and deployment notes#

  • Ship the built library, the manifest, and resources in the standard add-in folder structure from the packaging page.
  • Build separate binaries for Windows and macOS (and for Apple silicon and Intel if both are supported). List supported platforms in supportedOS.
  • General guidance, not Autodesk data: keep the template's compiler and runtime settings, and test on a machine without a developer toolchain, since missing redistributable runtimes show up only there.
  • Utility functions in Core/Utils.h: adsk::doEvents(), adsk::autoTerminate() (a C++ script ends automatically unless you turn this off) and adsk::terminate().

Tips and pitfalls#

Tip: Each reference topic names the header you need, so the reference tells you what to include.

Tip: General guidance: prototype the logic in Python, then port to C++ only the parts proven to be slow.

Warning: Declare every Fusion object with Ptr<T>; Autodesk says the smart pointer "will automatically handle adding and removing references". Do not delete API objects.

Warning: Most of Fusion, including your add-in, runs on a single main thread. Do not call the API from worker threads; use custom events as described in the event handlers page.

Warning: General guidance: regenerate project files from the current template after a Fusion update rather than reusing old project settings.

Practice exercise#

Create a C++ add-in from the template and make its run function build the same parametric washer from the sketches page: two concentric circles, find the annular profile by comparing areaProperties()->area(), extrude 2 mm. Add getLastError handling after each call. Expected result: pressing Run creates the washer; forcing a failure (for example, passing an invalid profile pointer) shows the error text rather than crashing.

  • Fusion API overview
  • Packaging and distributing add-ins
  • Debugging in VS Code
  • Event handlers

Sources

Checked against these Autodesk help topics (opens autodesk.com):

Related pages