# QAIRT API Migration Guide

On this page

- [Motivation](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#motivation)

    - [Impacted Systems](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#impacted-systems)
    - [ABI Compatibility](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#abi-compatibility)
    - [Ecosystem](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#ecosystem)
    - [Unification of QNN and SNPE](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#unification-of-qnn-and-snpe)
- [QAIRT C API Design Overview](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#qairt-c-api-design-overview)

    - [Structureless API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#structureless-api)
    - [Common Patterns](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#common-patterns)
    - [Interface Retrieval](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#interface-retrieval)
- [Migrating from QNN to QAIRT](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#migrating-from-qnn-to-qairt)

    - [QAIRT C++ Header-Only API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#qairt-c-header-only-api)
    - [Known Differences](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#known-differences)
    - [Migrating from SNPE to QAIRT](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#migrating-from-snpe-to-qairt)
- [Code Examples](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#code-examples)

    - [Retrieving an Interface](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#retrieving-an-interface)
    - [Creating a Logger](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#creating-a-logger)
    - [Creating and Configuring a Backend and Context](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#creating-and-configuring-a-backend-and-context)
    - [Executing a Context Binary](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#executing-a-context-binary)
- [Using the QAIRT API Package](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#using-the-qairt-api-package)

    - [Windows toolchains (MSVC)](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#windows-toolchains-msvc)
    - [Linux toolchains](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#linux-toolchains)
    - [Android toolchains](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#android-toolchains)
- [Binary and Library Renaming Map](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#binary-and-library-renaming-map)

    - [Runtime Backend Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#runtime-backend-libraries)
    - [System Library](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#system-library)
    - [Backend Extensions](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#backend-extensions)
    - [Stub Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#stub-libraries)
    - [Prepare and Skel Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#prepare-and-skel-libraries)
    - [Conversion and Execution Tools](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#conversion-and-execution-tools)
    - [CLI Tool Migration Notes](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#cli-tool-migration-notes)
- [Glossary](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#glossary)

## [Motivation](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id1)

Qualcomm currently offers two AI acceleration runtime products:
**Qualcomm AI Engine Direct (QNN)** and **Snapdragon Neural ProcessingEngine (SNPE)**. The **QAIRT API** consolidates these offerings into a
single, unified runtime and programming model.

QAIRT introduces a new API surface that is source-incompatible with QNN
and SNPE, while providing a strong guarantee of **Application BinaryInterface (ABI) compatibility** across QAIRT releases. Applications built
against one QAIRT version can upgrade to newer QAIRT runtime libraries
without recompilation.

This guide is intended to:

- Explain the design principles behind QAIRT
- Describe the scope and impact of migration
- Provide concrete examples for migrating from QNN/SNPE to QAIRT

Readers primarily interested in API concepts should review Sections 1–2.
Readers migrating existing applications should focus on Sections 3–6.

### [Impacted Systems](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id2)

Migration to the QAIRT API primarily affects applications that directly
link against QNN or SNPE runtime libraries.

Key considerations:

- Applications must transition from QNN/SNPE APIs to QAIRT APIs to
maintain equivalent functionality.
- QAIRT runtime libraries remain forward-compatible with future QAIRT
releases.
- Context binaries and DLCs generated using QAIRT Converters or the QNN
Context Binary Generator remain compatible.
- Context binaries generated by QNN tools remain loadable by QAIRT
backends, provided the binary format version is supported.
- `model.so` libraries produced by QNN converters are **notcompatible** with QAIRT. These models must be reconverted into DLC
format.

Language requirements:

- **QAIRT C API**: C99 or newer
- **QAIRT C++ API**: C++17 or newer

### [ABI Compatibility](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id3)

QAIRT guarantees ABI stability across releases of the runtime libraries.
This ensures:

- No recompilation is required when upgrading QAIRT libraries
- Existing binaries remain functional with newer runtimes
- Interfaces evolve only by extension, not removal

### [Ecosystem](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id4)

QAIRT supports both C and modern C++ integration strategies.

#### C and C++ Standards

- C API: C99+
- C++ Header-Only API: C++17

The C API ensures maximum portability and ABI stability. The header-only
C++ API provides a safer, more expressive interface using modern C++
patterns.

### [Unification of QNN and SNPE](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id5)

QAIRT unifies QNN and SNPE functionality under a single API surface.
Applications can:

- Combine model-level abstractions (formerly SNPE-centric)
- Use accelerator-specific backend APIs (formerly QNN-centric)

Model-centric features emphasize **Deep Learning Containers (DLC)**,
while backend APIs provide fine-grained control over execution,
configuration, and graph management.

## [QAIRT C API Design Overview](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id6)

This section will give an overview of new design principles and patterns
with an emphasis on differences from QNN and SNPE APIs to QAIRT APIs.

This section focuses on the QAIRT C API. It is recommended that users
interested in the QAIRT C++ go to section
[QAIRT C++ Header-Only API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#cpp-header-only-api).

### [Structureless API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id7)

To preserve ABI compatibility, QAIRT avoids exposing compound structure
in the API. Instead, all non-primitive objects are represented as:

- An opaque handle
- An associated interface (function table)

#### Example: Struct to Handle Migration

QNN-style structure:

typedef struct {
        uint32_t dataSize;
        void* data;
    } Buffer_t;
    Copy to clipboard

Equivalent QAIRT-style handle and interface:

typedef void* BufferHandle_t;
    
    void Buffer_create(BufferHandle_t* outHandle);
    void Buffer_free(BufferHandle_t handle);
    void Buffer_setDataSize(BufferHandle_t buffer, uint32_t dataSize);
    void Buffer_getDataSize(BufferHandle_t buffer, uint32_t* dataSize);
    void Buffer_setData(BufferHandle_t buffer, void* data);
    void Buffer_getData(BufferHandle_t buffer, void** data);
    
    // Interface that implements these functions
    typedef struct {
        uint64_t size;
        Qairt_GetInterfaceFn_t getInterface;
        BufferCreateFn_t create;
        BufferFreeFn_t  free;
        BufferSetDataSizeFn_t setDataSize;
        BufferGetDataSizeFn_t getDataSize;
        BufferSetDataFn_t setData;
        BufferGetDataFn_t getData;
    } Buffer_t;
    Copy to clipboard

A user may have had:

// Create Buffer_t instance
    Buffer_t buffer;
    // Set members
    buffer.dataSize = 10;
    buffer.data = static_cast<void*>(new uint8_t[10]);
    // Access previously set member
    if(buffer.dataSize > 5) std::cout << "Data size is large!";
    // Structure is automatically deleted when it goes out of scope
    Copy to clipboard

The corresponding QAIRT API usage looks like:

// Create buffer handle and
    // interface.
    BufferHandle_t buffer;
    Buffer_t bufferInterface;
    bufferInterface->create(&buffer);
    
    // Set members
    bufferInterface->setDataSize(buffer, 10);
    void* data = static_cast<void*>(new uint8_t[10]);
    bufferInterface->setData(buffer, data);
    
    // Access previously set member
    uint32_t dataSize = 0;
    bufferInterface->getDataSize(buffer, &dataSize);
    if (dataSize > 5) std::cout << "Data size is large!";
    
    // Explicitly free handle
    bufferInterface->free(buffer);
    Copy to clipboard

#### Lifecycle Management

Since clients of the QAIRT C API are not directly creating data
containing structures, they manage the lifetime of the structures via
creation and freeing of handles.

This is the same as handle based objects in the existing QNN API, however
it differs from non-handle based structures which are inherently client
managed in QNN.

In QAIRT, handle lifetimes are managed explicitly and fall into two
distinct categories: **owning handles** and **non-owning handles**.

1. Handles are valid only while the originating library is loaded.
2. Handles returned from `*_create()` are **owning handles** and
**must** be released using the corresponding `*_free()` call. The
lifecycle of handles created by `*_create()` is managed by the
client.
3. Handles obtained from getter-style APIs (functions other than
`*_create()`) are **non-owning handles** and **must not be freedby the client**.

If an owning object is modified or destroyed, any non-owning handles
previously retrieved from that object become invalid and must no longer
be used.

Note

In the QAIRT C++ Header-Only API, lifecycle management (including
ownership tracking of non-owning handles) is handled automatically
via RAII.

### [Common Patterns](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id8)

#### Compound Types

Compound types are types which are composed of multiple other types.

typedef struct {
        uint32_t dataSize;
        void* data;
    } Buffer_t;
    
    typedef struct {
        uint32_t offset;
        float scale;
    } ScaleOffset_t;
    
    typedef struct {
        const char* name;
        ScaleOffset_t scaleOffset;
        Buffer_t buffer;
    } Tensor_t;
    Copy to clipboard

Compound types in QAIRT utilize the same handle and interface pattern as
before, with the ability to set and retrieve encapsulated handles on the
encapsulating object.

// Definition of Buffer
    typedef void* BufferHandle_t;
    Buffer_create(BufferHandle_t* outHandle);
    Buffer_free(BufferHandle_t inHandle);
    Buffer_setDataSize(BufferHandle_t buffer, uint32_t dataSize);
    Buffer_getDataSize(BufferHandle_t buffer, uint32_t* dataSize);
    Buffer_setData(BufferHandle_t buffer, void* data);
    Buffer_getData(BufferHandle_t buffer, void** offset);
    
    typedef struct {
        BufferCreate create;
        BufferFree free;
        BufferSetDataSize setDataSize;
        BufferGetDataSize getDataSize;
        BufferSetData setData;
        BufferGetData getData;
    } Buffer_t;
    
    // Definition of ScaleOffset
    typedef void* ScaleOffsetHandle_t;
    ScaleOffset_create(ScaleOffsetHandle_t* outHandle);
    ScaleOffset_free(ScaleOffsetHandle_t inHandle);
    ScaleOffset_setOffset(ScaleOffsetHandle_t so, uint32_t offset);
    ScaleOffset_getOffset(ScaleOffsetHandle_t so, uint32_t* offset);
    ScaleOffset_setScale(ScaleOffsetHandle_t so, float scale);
    ScaleOffset_getScale(ScaleOffsetHandle_t so, float* scale);
    
    typedef struct {
        ScaleOffsetCreate create;
        ScaleOffsetFree free;
        ScaleOffsetSetOffset setOffset;
        ScaleOffsetGetOffset getOffset;
        ScaleOffsetSetScale setScale;
        ScaleOffsetGetScale getScale;
    } ScaleOffset_t;
    
    // Definition of Tensor
    typedef void* TensorHandle_t;
    Tensor_create(TensorHandle_t* outHandle);
    Tensor_free(TensorHandle_t inHandle);
    Tensor_setName(TensorHandle_t tensor, const char* name);
    Tensor_getName(TensorHandle_t tensor, const char** name);
    Tensor_getBuffer(TensorHandle_t tensor, BufferHandle_t* buffer);
    Tensor_setBuffer(TensorHandle_t tensor, BufferHandle_t buffer);
    Tensor_setScaleOffset(TensorHandle_t tensor, ScaleOffsetHandle_t so);
    Tensor_getScaleOffset(TensorHandle_t tensor, ScaleOffsetHandle_t* so);
    
    typedef struct {
        TensorCreate create;
        TensorFree free;
        TensorSetName setName;
        TensorGetName getName;
        TensorSetBuffer setBuffer;
        TensorGetBuffer getBuffer;
        TensorSetScaleOffset setScaleOffset;
        TensorGetScaleOffset getScaleOffset;
    } Tensor_t;
    Copy to clipboard

*Encapsulated handles retrieved via getters are not client-owned and mustnot be freed.*

#### Unions

Union-like constructs are modeled as variant-style objects, exposing:

- Explicit setters for each possible type
- A `getType()` function to query the active variant

This avoids undefined ownership and invalid state combinations.

#### Arrays

Arrays are accessed through count-and-index patterns to avoid client-side
allocations:

Qairt_ErrorHandle_t getNumElements(InType_t in, uint32_t* numElements);
    Qairt_ErrorHandle_t getElementAt(InType_t in, uint32_t index, OutType_t* out);
    Copy to clipboard

As an example, a structure in QNN like so:

// An op config, with an array
    // of input tensors
    typedef struct {
        OpType_t type;
        uint32_t numInputs;
        Tensor_t* inputs;
    } OpConfig_t;
    Copy to clipboard

Becomes the following in QAIRT:

// An op config, with an array
    // of input tensors
    
    typedef void* OpConfigHandle_t;
    OpConfig_setType(OpConfigHandle_t op, OpType_t type);
    OpConfig_getType(OpConfigHandle_t op, OpType_t* type);
    OpConfig_addInput(OpConfigHandle_t op, TensorHandle_t input);
    OpConfig_getNumInputs(OpConfigHandle_t op, uint32_t* numInputs);
    OpConfig_getInputAt(OpConfigHandle_t op, uint32_t idx, TensorHandle_t* input);
    
    typedef struct {
        OpConfigCreate create;
        OpConfigFree free;
        OpConfigSetType setType;
        OpConfigAddInput addInput;
        OpConfigGetNumInputs getNumInputs;
        OpConfigGetInputAt getInputAt;
    } OpConfig_t;
    Copy to clipboard

This usage in QNN:

// Create op config
    OpConfig_t opConfig;
    // Set op type
    opConfig.type = RELU_OP;
    // Create and add tensor to the config
    opConfig.numInputs = 1;
    Tensor_t* inputs = new Tensor_t[1];
    inputs[0].name = "Tensor";
    opConfig.inputs = inputs;
    
    // Extract the input from the op
    std::cout << "There are " << opConfig.numInputs
              << " inputs: " << opConfig.inputs[0].name;
    Copy to clipboard

Becomes the following in QAIRT:

// Create op config
    OpConfigHandle_t opConfig;
    OpConfig_t opConfigInterface;
    opConfigInterface->create(&opConfig);
    // Set op type
    opConfigInterface->setType(opConfig, RELU_OP);
    // Create and add tensor to the config
    TensorHandle_t tensor;
    tensorInterface->create(&tensor);
    tensorInterface->setName(tensor, "Tensor");
    opConfigInterface->addInput(opConfig, tensor);
    
    // Extract the input of the op
    TensorHandle_t retrievedTensor;
    uint32_t numInputs;
    opConfigInterface->getNumInputs(opConfig, &numInputs);
    opConfigInterface->getInputAt(opConfig, 0, &retrievedTensor);
    
    const char* name;
    tensorInterface->getName(retrievedTensor, &name);
    
    std::cout << "There are " << numInputs << " inputs: " << name;
    Copy to clipboard

### [Interface Retrieval](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id9)

QAIRT introduces a standardized interface discovery mechanism:

- All interfaces are versioned
- Functions within an interface version will never be removed
- Interfaces contain a `size` field allowing backward compatibility
checks

#### Interface IDs

Each interface can be retrieved from an interface identifier – a
numerical value defined in the respective component header for that
interface. This value is used in the function
`QairtInterface_getInterface()`. Here is a generic example

ExampleInterfaceV1_t* iface;
    QairtInterface_getInterface(QAIRT_EXAMPLE_INTERFACE_V1_ID, (void**)&iface);
    iface->function();
    Copy to clipboard

#### Compatibility Checking

Within a major interface version, it is guaranteed that behavior will not
be removed when upgrading to new runtime libraries. However, it may be
possible that if a client would like to use an older runtime library
without recompilation that the old runtime library is missing
functionality. To address these cases, each interface contains a size
member which can be used to check if a function is available to be
called. As an example

if (iface->size > offsetof(ExampleInterfaceV1_t, function)) {
        iface->function();
    }
    Copy to clipboard

The C++ API performs this validation automatically and throws exceptions
if unsupported functionality is called.

auto example = api.make<qairt::Example>();
    try {
       example->function();
    } catch(qairt::Exception& e) {
       std::cerr << "Function call failed with error" << e.what();
    }
    Copy to clipboard

## [Migrating from QNN to QAIRT](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id10)

This section focuses on migrating applications that currently use the QNN
API to the QAIRT API. The examples in this section use the QAIRT C++
Header-Only API, which is the recommended integration path for C++
applications.

### [QAIRT C++ Header-Only API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id11)

It is recommended that C++ applications migrate to QAIRT using the QAIRT
C++ Header-Only API rather than integrating directly with the C API if
possible.

The QAIRT C++ Header-Only API provides the following benefits:

- Modern C++ abstractions for all QAIRT objects
- Automatic interface retrieval and compatibility checking
- RAII-based lifetime management for handles
- Reduced boilerplate when porting existing QNN-based code

All QAIRT C++ objects are created through a central `qairt::Api`
object, which is responsible for loading the runtime library and serving
as a factory for all other QAIRT objects. System-level operations (DLC
loading, binary metadata) use a separate `qairt::SystemApi` object that
loads `libQairtSystem.so`.

qairt::Api api("libQairtHtp.so");
    auto log = api.makeShared<qairt::Log>(logCallback, logLevel);
    auto backend = api.makeShared<qairt::Backend>(*log);
    Copy to clipboard

The lifetime of all QAIRT objects created through the factory is tied to
the lifetime of the `qairt::Api` instance.

### [Known Differences](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id12)

While QAIRT maintains many of the same conceptual models as QNN, there
are several important differences that users should be aware of when
migrating existing code.

#### Tensor Properties

In QNN, tensor ownership and mutability are represented using a single
enumeration value. QAIRT replaces this model with a dedicated
`TensorProperties` object to improve extensibility and clarity.

auto tensorProperties = api.make<qairt::TensorProperties>();
    tensorProperties.setIsInput(true);
    tensorProperties.setIsUpdateable(true);
    
    auto tensor = api.make<qairt::Tensor>();
    tensor.setTensorProperties(tensorProperties);
    Copy to clipboard

#### Ion Memory

ION memory handles are no longer supported in QAIRT. Applications that
previously used ION memory should migrate to using DMA Buffer file
descriptors instead. The QAIRT memory API (`QairtMem`) provides DMA
buffer management through the standard handle and interface pattern.

#### Configurations

QAIRT configurations are conceptually similar to those in QNN, but their
structure has changed. Instead of supplying a vector of configuration
objects, QAIRT uses tabular configuration objects that group related
configuration options together.

auto contextConfig = api.make<qairt::ContextConfiguration>();
    contextConfig.setPersistentBinary(true);
    contextConfig.setPriority(QAIRT_PRIORITY_HIGH);
    Copy to clipboard

#### Error Handling

The standalone Error API has been removed in QAIRT.

### [Migrating from SNPE to QAIRT](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id13)

SNPE users will find that the familiar builder pattern is preserved in
QAIRT through `QairtSystemBuilder`, which provides a high-level API
that closely mirrors the SNPE `SNPEBuilder` workflow.

#### QairtSystemBuilder

`QairtSystemBuilder` follows the same fluent builder pattern as
`SNPEBuilder`. It accumulates configuration via setter calls and
performs the full backend + context + graph initialization in a single
`build()` call:

auto systemApi = std::make_shared<qairt::SystemApi>("libQairtSystem.so");
    auto systemDlc = systemApi->makeShared<qairt::SystemDlc>("model.dlc");
    
    auto builder = systemApi->make<qairt::QairtSystemBuilder>();
    builder.setDlc(systemDlc)
           .setBackendType(qairt::BackendType::Htp)
           .setLogLevel(qairt::LogLevel::Warn)
           .setPerfProfile(qairt::PerfProfile::HighPerformance);
    
    auto qairt = builder.build();  // fully initialized, ready for inference
    Copy to clipboard

#### Execution

After building, inference follows a similar pattern to SNPE — get graph
info, prepare buffers, execute:

auto& graphInfo = qairt.getGraphInfoAt(0);
    auto& inputs = graphInfo.getGraphInputs();
    auto& outputs = graphInfo.getGraphOutputs();
    
    // Allocate and fill input/output buffers...
    qairt.executeGraph(graphInfo.getGraphName(), inputData, outputData);
    Copy to clipboard

#### API Mapping

| SNPE | QAIRT |
| --- | --- |
| `SNPEBuilder` | `qairt::QairtSystemBuilder` |
| `SNPEBuilder::setDlcPath()` | `builder.setDlc(systemDlc)` |
| `SNPEBuilder::setPerformanceProfile()` | `builder.setPerfProfile(qairt::PerfProfile::...)` |
| `SNPEBuilder::setRuntimeProcessorOrder()` | `builder.setBackendType(qairt::BackendType::...)` |
| `SNPE::execute()` | `qairt.executeGraph(graphName, inputs, outputs)` |
| `libSNPE.so` | Per-backend: `libQairtCpu.so`, `libQairtHtp.so`, etc. |

#### Key Differences from SNPE

- **Per-backend libraries**: SNPE used a single `libSNPE.so` for all
backends. QAIRT provides separate backend libraries
(`libQairtCpu.so`, `libQairtHtp.so`, etc.), giving applications
finer control over which accelerators are loaded.
- **DLC compatibility**: Existing SNPE DLC files are compatible with
QAIRT and can be loaded directly via `qairt::SystemDlc`.
- **Low-level access**: In addition to the high-level builder path,
QAIRT also exposes the Backend → Context → Graph lifecycle directly
(see [QAIRT C++ Header-Only API](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#cpp-header-only-api)) for applications that need
finer-grained control.

## [Code Examples](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id14)

This section provides examples of basic API usage of the QAIRT C++
Header-Only API. More detailed examples can be found in the QAIRT sample
application (QairtSampleApp.cpp). Users are encouraged to reference the
sample code for comprehensive usage patterns.

### [Retrieving an Interface](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id15)

The first step in using the QAIRT API is to retrieve an interface. This
is easily done with the QAIRT C++ API.

qairt::Api api("libQairtHtp.so");
    auto tensor = api.make<qairt::Tensor>();
    Copy to clipboard

Interfaces are retrieved lazily and automatically as objects are created
through the API factory.

### [Creating a Logger](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id16)

To enable logging, a user can create a shared log object. This object
may be shared across multiple QAIRT components and configured using a
callback.

auto log = api->makeShared<qairt::Log>(
            [](const char* fmt, QairtLog_Level_t level, uint64_t timestamp, void* /*userData*/, va_list argp) {
              (void)timestamp;
              char str[1000];
              auto deferredVsnprintf = [&] {
                str[0] = '\0';
                vsnprintf(str, sizeof(str), fmt, argp);
                return const_cast<const char*>(str);
              };
              std::cerr << "\e[93m#LOG2#\t" << deferredVsnprintf() << "\e[0m\n";
            },
            logLevel);
    Copy to clipboard

### [Creating and Configuring a Backend and Context](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id17)

After creating the API object, a backend instance can be created and
configured with backend-specific options.

qairt::Api api("libQairtHtp.so");
    auto backend = api.makeShared<qairt::Backend>(*log);
    
    // Core context configuration
    auto contextConfig = api.make<qairt::ContextConfiguration>();
    contextConfig.setPersistentBinary(true);
    contextConfig.setPriority(QAIRT_PRIORITY_HIGH);
    
    // HTP-specific context configuration
    auto htpConfig = api.make<qairt::HtpContextCustomConfig>();
    htpConfig.setEnableWeightSharing(true);
    
    // Group registration controls shared spill/fill memory between contexts
    auto groupReg = api.make<qairt::HtpContextGroupRegistration>();
    groupReg.setMaxSpillFill(1024);
    htpConfig.setGroupRegistration(groupReg);
    
    // Custom configs extend the core ContextCustomConfig interface,
    // allowing backend-specific options to be passed through the
    // backend-agnostic ContextConfiguration.
    contextConfig.setCustomConfig(htpConfig);
    
    auto context = backend->createContext(contextConfig);
    Copy to clipboard

Each QAIRT component (Backend, Context, Graph, Device) has its own
custom config hierarchy. Backend-specific types like
`HtpContextCustomConfig` extend the core `ContextCustomConfig`
interface, allowing backend-agnostic code to pass through
backend-specific options. Refer to the QAIRT C++ headers under
`QairtCpp/HTP/`, `QairtCpp/GPU/`, and `QairtCpp/DSP/` for the
full set of backend-specific configuration options.

### [Executing a Context Binary](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id18)

This example demonstrates loading and executing a context binary using
the QAIRT API.

auto context = backend->createContextFromBinary(config, rawBuffer, profile);
    
    auto graph = context->retrieveGraph("GraphName");
    graph->finalize();
    graph->execute(inputs, outputs);
    Copy to clipboard

More details on the usage mechanics can be found in the sample
application.

## [Using the QAIRT API Package](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id19)

The QAIRT package includes:

- QAIRT C and C++ headers
- CPU, GPU, HTP, DSP, and LPAI backend libraries
- Sample applications
- CLI tools (`qairt-net-run`, `qairt-dlc-prepare`)

Supported platforms (runtime execution):

- Linux x86\_64
- Android AArch64
- Windows x64

Note

QAIRT prebuilt tools and libraries are provided for multiple
toolchains and architectures across these platforms, as outlined
below.

### [Windows toolchains (MSVC)](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id20)

- `x86_64-windows-msvc`
- `aarch64-windows-msvc`
- `arm64x-windows-msvc`

These toolchains provide `qairt-net-run`, `qairt-dlc-prepare`, and
matching QAIRT CPU/GPU/HTP runtime libraries (`QairtCpu`,
`QairtGpu`, `QairtHtp`).

### [Linux toolchains](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id21)

- `x86_64-linux-clang`
- `aarch64-oe-linux-gcc8.2`
- `aarch64-oe-linux-gcc9.3`
- `aarch64-oe-linux-gcc11.2`
- `aarch64-ubuntu-gcc9.4`

Linux distributions include `qairt-net-run` and `qairt-dlc-prepare`
for each supported toolchain.

### [Android toolchains](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id22)

- `aarch64-android`

Android packages provide QAIRT execution and preparation tools targeting
AArch64 devices.

## [Binary and Library Renaming Map](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id23)

### [Runtime Backend Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id24)

| QNN | QAIRT | Notes |
| --- | --- | --- |
| libQnnCpu.so / QnnCpu.dll | libQairtCpu.so / QairtCpu.dll |  |
| libQnnGpu.so / QnnGpu.dll | libQairtGpu.so / QairtGpu.dll |  |
| libQnnHtp.so / QnnHtp.dll | libQairtHtp.so / QairtHtp.dll |  |
| libQnnDsp.so | libQairtDsp.so |  |
| libQnnLpai.so | libQairtLpai.so |  |

### [System Library](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id25)

| QNN | QAIRT | Notes |
| --- | --- | --- |
| libQnnSystem.so / QnnSystem.dll | libQairtSystem.so / QairtSystem.dll | Ships under `QAIRT/lib/` in the SDK |

### [Backend Extensions](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id26)

The backend extension libraries have been renamed from
`NetRunExtensions` to `BackendExtensions`:

| QNN | QAIRT |
| --- | --- |
| libQnnCpuNetRunExtensions.so | libQairtCpuBackendExtensions.so |
| libQnnGpuNetRunExtensions.so | libQairtGpuBackendExtensions.so |
| libQnnHtpNetRunExtensions.so | libQairtHtpBackendExtensions.so |
| libQnnDspNetRunExtensions.so | libQairtDspBackendExtensions.so |
| libQnnLpaiNetRunExtensions.so | libQairtLpaiBackendExtensions.so |

### [Stub Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id27)

Stub libraries follow a consistent renaming pattern:

| QNN | QAIRT |
| --- | --- |
| libQnnHtpV##Stub.so | libQairtHtpV##Stub.so |
| libQnnDspV##Stub.so | libQairtDspV##Stub.so |
| libQnnLpaiStub.so | libQairtLpaiStub.so |

### [Prepare and Skel Libraries](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id28)

| QNN | QAIRT | Notes |
| --- | --- | --- |
| libQnnHtpPrepare.so | libQairtHtpPrepare.so | Offline graph preparation |
| libQnnHtpV{ver}Skel.so | libQairtHtpV{ver}Skel.so | Hexagon target libraries |
| libQnnDspV{ver}Skel.so | libQairtDspV{ver}Skel.so | Hexagon target libraries |

### [Conversion and Execution Tools](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id29)

| QNN | QAIRT | Notes |
| --- | --- | --- |
| qnn-net-run | qairt-net-run | See [CLI Tool Migration Notes](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#cli-tool-migration-notes) |
| qnn-context-binary-generator | qairt-dlc-prepare | Renamed to reflect DLC-centric model |

### [CLI Tool Migration Notes](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id30)

#### qairt-net-run

`qairt-net-run` replaces `qnn-net-run` with a simplified interface
focused on DLC-based execution.

**New flags:**

| Flag | Description |
| --- | --- |
| `--use_cpu`, `--use_gpu`, `--use_htp` | Convenience backend selection (no need to specify `.so` path) |
| `--use_high_level_apis` | Uses simplified high-level QAIRT APIs for model execution. This<br>flag provides a migration path for SNPE users accustomed to the<br>higher-level `SNPE::execute()` style interface. |
| `--input_name` / `--input_dimensions` | Runtime tensor resizing (e.g.,<br>`--input_name=input --input_dimensions=1,512,512,3`) |

**Renamed flags:**

| qnn-net-run | qairt-net-run |
| --- | --- |
| `--dlc_path` | `--input_dlc` |
| `--retrieve_context` | `--input_context_binary` |

**Removed (not applicable in QAIRT):**

| Flag | Reason |
| --- | --- |
| `--model` / `--model_prefix` | `model.so` format is not supported; use DLC |
| `--op_packages` | Op packages are not supported in QAIRT |

#### qairt-dlc-prepare

`qairt-dlc-prepare` replaces `qnn-context-binary-generator`. The
tool name reflects the shift to DLC as the primary model format. The
core functionality — offline preparation of context binaries — remains
the same.

## [Glossary](https://docs.qualcomm.com/doc/80-63442-10/topic/migration-guide.html#id31)

- ABI (Application Binary Interface)
    - The low-level binary contract between compiled applications and
libraries.

- Backend
    - An accelerator-specific runtime implementation (CPU, GPU, HTP,
DSP, LPAI).

- Backend Extension
    - The mechanism by which backends provide custom configuration
options (e.g., HTP weight sharing, group registration) that extend
the core QAIRT API. Backend extensions allow backend-specific
types to be passed through backend-agnostic interfaces like
`ContextConfiguration`.

- Context Binary
    - A serialized execution context generated by QAIRT or QNN tools.

- DLC (Deep Learning Container)
    - The primary model representation format used by QAIRT.

- DMA Buffer
    - Direct Memory Access buffer; the replacement for ION memory
handles in QAIRT for shared memory between application and
accelerator.

- Handle
    - An opaque reference to a runtime-managed object.

- Interface
    - A versioned function table used to operate on handles.

- Non-owning Handle
    - A handle whose lifetime is managed by another object and **mustnot be freed by the client**. Non-owning handles are typically
returned by getter-style APIs (i.e., functions other than
`_create()`), and they become invalid if the owning object is
modified or destroyed.

- QAIRT
    - Qualcomm AI Runtime, a unified API consolidating QNN and SNPE.

- QairtSystemBuilder
    - A fluent builder class that provides a high-level API for QAIRT
initialization, analogous to SNPE’s `SNPEBuilder`.

- RAII
    - Resource Acquisition Is Initialization; a C++ lifetime management
pattern.

- SystemApi
    - A separate API entry point (`qairt::SystemApi`) for
system-level operations including DLC loading, binary metadata
inspection, and high-level builder construction.

Last Published: Jun 04, 2026

[Previous Topic
How to Use the QAIRT Sample App](https://docs.qualcomm.com/bundle/publicresource/80-63442-10/topics/tutorial_sample_app_linux.md) [Next Topic
C API](https://docs.qualcomm.com/bundle/publicresource/80-63442-10/topics/index_c-api.md)