Program Listing for File TransportBackend.h¶
↰ Return to documentation for file (runtime/include/TransportBackend.h)
// Copyright 2026 Xanadu Quantum Technologies Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The plugin ABI for out-of-tree transport backends.
//
// A transport backend is a shared library that implements a TransportSession role (controller or
// coprocessor) and exports the matching factory symbol.
#pragma once
#ifndef TRANSPORTBACKEND_H
#define TRANSPORTBACKEND_H
#include <cstdint>
#include <exception>
#include <iostream>
#include "Transport.hpp"
#define CATALYST_TRANSPORT_CONTROLLER_FACTORY_SYMBOL "CatalystTransportControllerFactory"
#define CATALYST_TRANSPORT_COPROCESSOR_FACTORY_SYMBOL "CatalystTransportCoprocessorFactory"
// Backend ABI version and capabilities.
//
// A backend exports `uint32_t CatalystTransportAbiVersion(void)` and
// `const CatalystTransportCaps *CatalystTransportQueryCaps(void)`; the
// CATALYST_TRANSPORT_BACKEND_CAPS macro below defines both. The loader checks them before calling
// a factory:
// - no CatalystTransportAbiVersion: a backend built before versioning, loaded as version 1, which
// reports no capabilities and whose sessions the runtime deletes;
// - a version newer than CATALYST_TRANSPORT_ABI_VERSION: refused, naming both versions;
// - a role missing from `roles`: refused.
// A backend built against an older version keeps working, because the session interface in
// Transport.hpp follows these rules:
// - virtual methods are only appended, never removed or reordered;
// - the session base classes gain no data members;
// - the runtime never calls a method added in version N on a backend reporting a lower version.
#define CATALYST_TRANSPORT_ABI_VERSION 2u
#define CATALYST_TRANSPORT_ABI_VERSION_SYMBOL "CatalystTransportAbiVersion"
#define CATALYST_TRANSPORT_QUERY_CAPS_SYMBOL "CatalystTransportQueryCaps"
// CatalystTransportCaps::roles
#define CATALYST_TRANSPORT_ROLE_BIT_CONTROLLER (1u << 0)
#define CATALYST_TRANSPORT_ROLE_BIT_COPROCESSOR (1u << 1)
// CatalystTransportCaps::frame_modes
#define CATALYST_TRANSPORT_FRAME_BL16 (1u << 0) // existing 16 B frame layout
// CatalystTransportCaps::ordering
#define CATALYST_TRANSPORT_ORDER_IN_ORDER 0u // a payload lands before the word written after it
// CatalystTransportCaps::mem_kinds and ::conventions, e.g. CATALYST_TRANSPORT_MEM_BIT(CpuRam).
#define CATALYST_TRANSPORT_MEM_BIT(KIND) \
(1u << static_cast<unsigned>(catalyst::transport::MemKind::KIND))
#define CATALYST_TRANSPORT_CONV_BIT(CONVENTION) \
(1u << static_cast<unsigned>(catalyst::transport::CoprocConvention::CONVENTION))
extern "C" {
typedef struct {
uint32_t abi_version; // CATALYST_TRANSPORT_ABI_VERSION the backend was built with
uint32_t roles; // CATALYST_TRANSPORT_ROLE_BIT_*
uint32_t mem_kinds; // CATALYST_TRANSPORT_MEM_BIT(...)
uint32_t frame_modes; // CATALYST_TRANSPORT_FRAME_*
uint32_t max_payload_bytes; // largest request payload per message, whatever the frame mode
uint32_t ordering; // CATALYST_TRANSPORT_ORDER_*
const char *name; // e.g. "cpu_verbs"
uint32_t max_reply_bytes; // largest reply per message
uint32_t conventions; // CATALYST_TRANSPORT_CONV_BIT(...); 0 for controllers
uint32_t max_work_items; // work items a controller can commit
uint32_t reserved; // zero
void (*destroy_session)(void *session); // deletes a session this library created
} CatalystTransportCaps;
using CatalystTransportAbiVersionFn = uint32_t();
using CatalystTransportQueryCapsFn = const CatalystTransportCaps *();
}
// Defines CatalystTransportAbiVersion and CatalystTransportQueryCaps for an in-tree backend.
// e.g. CATALYST_TRANSPORT_BACKEND_CAPS("cpu_verbs", CATALYST_TRANSPORT_ROLE_BIT_CONTROLLER,
// CATALYST_TRANSPORT_MEM_BIT(CpuRam), 0, 8, 8, 1)
#define CATALYST_TRANSPORT_BACKEND_CAPS(NAME, ROLES, MEM_KINDS, CONVENTIONS, MAX_PAYLOAD, \
MAX_REPLY, WORK_ITEMS) \
extern "C" uint32_t CatalystTransportAbiVersion() { return CATALYST_TRANSPORT_ABI_VERSION; } \
extern "C" const CatalystTransportCaps *CatalystTransportQueryCaps() { \
static const CatalystTransportCaps caps = { \
CATALYST_TRANSPORT_ABI_VERSION, \
(ROLES), \
(MEM_KINDS), \
CATALYST_TRANSPORT_FRAME_BL16, \
(MAX_PAYLOAD), \
CATALYST_TRANSPORT_ORDER_IN_ORDER, \
(NAME), \
(MAX_REPLY), \
(CONVENTIONS), \
(WORK_ITEMS), \
0, \
[](void *s) { delete static_cast<catalyst::transport::TransportSession *>(s); }}; \
return ∩︀ \
}
// The factory signatures backends must export with C linkage.
extern "C" {
using CatalystTransportControllerFactoryFn = catalyst::transport::ControllerSession *(const char *);
using CatalystTransportCoprocessorFactoryFn =
catalyst::transport::CoprocessorSession *(const char *);
}
// A helper template macro to generate the <IDENTIFIER>Factory function.
// e.g. GENERATE_TRANSPORT_CONTROLLER_FACTORY(CatalystTransportController, make_controller)
// where `make_controller(const std::string &config) -> ControllerSession*`.
#define GENERATE_TRANSPORT_CONTROLLER_FACTORY(IDENTIFIER, BUILDER) \
extern "C" catalyst::transport::ControllerSession *IDENTIFIER##Factory(const char *config) { \
try { \
return (BUILDER)(config ? std::string(config) : std::string()); \
} catch (const std::exception &e) { \
std::cerr << "[transport] controller factory failed: " << e.what() << "\n"; \
return nullptr; \
} catch (...) { \
std::cerr << "[transport] controller factory failed: unknown exception\n"; \
return nullptr; \
} \
}
// e.g. GENERATE_TRANSPORT_COPROCESSOR_FACTORY(CatalystTransportCoprocessor, make_coprocessor)
// where `make_coprocessor(const std::string &config) -> CoprocessorSession*`.
#define GENERATE_TRANSPORT_COPROCESSOR_FACTORY(IDENTIFIER, BUILDER) \
extern "C" catalyst::transport::CoprocessorSession *IDENTIFIER##Factory(const char *config) { \
try { \
return (BUILDER)(config ? std::string(config) : std::string()); \
} catch (const std::exception &e) { \
std::cerr << "[transport] coprocessor factory failed: " << e.what() << "\n"; \
return nullptr; \
} catch (...) { \
std::cerr << "[transport] coprocessor factory failed: unknown exception\n"; \
return nullptr; \
} \
}
#endif // TRANSPORTBACKEND_H