Skip to main content

C++ API

Repository: luxai-qtrobot/magpie-cpp · Standard: C++14 · Build system: CMake

Language references: Python · C++ · TypeScript / JavaScript

Libraries and headers​

Package or targetCapabilityRepresentative headers
libmagpieCore API, ZeroMQ, values, serialization, schemas, nodes, discoverymagpie/magpie.hpp, transport/zmq_*, schema/*
libmagpie-mqttMQTT connection, streams, and RPCtransport/mqtt_connection.hpp, mqtt_*
libmagpie-webrtcWebRTC connection, signaling, streams, and RPCtransport/webrtc_connection.hpp, webrtc_*
libmagpie-videoRaw and JPEG image framesframes/image_frame.hpp, image_frame_jpeg.hpp
libmagpie-audioRaw and FLAC audio framesframes/audio_frame.hpp, audio_frame_flac.hpp

Feature flags include MAGPIE_WITH_MQTT, MAGPIE_WITH_WEBRTC, MAGPIE_WITH_VIDEO, MAGPIE_WITH_AUDIO, MAGPIE_BUILD_EXAMPLES, and MAGPIE_BUILD_TESTS.

Core communication API​

Class and methodParameters and returnBehavior
StreamWriter::write(const Frame&, topic)Frame plus topic; returns voidDirect write when queueSize <= 0; otherwise queues a cloned frame and drops the oldest item when full.
StreamWriter::close()Returns voidDrains the writer queue, closes transport resources, and is idempotent.
StreamReader::read(outFrame, outTopic, timeoutSec=-1)Writes a std::unique_ptr<Frame> and topic; returns booltrue when an item is read; false on timeout or close. Negative timeout waits indefinitely.
StreamReader::close()Returns voidStops the reader and closes the transport.
RpcRequester::call(const Value&, timeoutSec=-1)Raw request; returns ValueThrows timeout subclasses or std::runtime_error after close.
RpcRequester::call(method, params={}, timeoutSec=-1)Schema method and Value::Dict; returns unwrapped ValueRequires a schema and throws JsonRpcError for protocol errors.
RpcRequester::close()Returns voidReleases requester resources; isClosed() reports state.
RpcResponder::respond(handler=nullptr, timeoutSec=-1)Value(const Value&) handler; returns boolHandles one request. The handler is optional when a schema is attached.
RpcResponder::close()Returns voidReleases responder resources; isClosed() reports state.

handleOnce() remains as a backward-compatible alias for respond(). New code should use respond().

Streaming example​

#include <magpie/frames/primitive_frames.hpp>
#include <magpie/transport/zmq_stream_reader.hpp>
#include <magpie/transport/zmq_stream_writer.hpp>

magpie::ZmqStreamWriter writer("tcp://*:5555");
magpie::ZmqStreamReader reader("tcp://127.0.0.1:5555", "robot/state");

magpie::StringFrame outgoing("ready");
writer.write(outgoing, "robot/state");

std::unique_ptr<magpie::Frame> incoming;
std::string topic;
if (reader.read(incoming, topic, 5.0)) {
if (auto* text = dynamic_cast<magpie::StringFrame*>(incoming.get())) {
magpie::Logger::info(text->value());
}
}

reader.close();
writer.close();

RPC example​

#include <magpie/serializer/value.hpp>
#include <magpie/transport/zmq_rpc_responder.hpp>

magpie::ZmqRpcResponder server("tcp://*:5556");

server.respond([](const magpie::Value& request) {
magpie::Value::Dict reply;
reply["ready"] = magpie::Value::fromBool(true);
reply["echo"] = request;
return magpie::Value::fromDict(reply);
}, 1.0);

Transport classes​

ZeroMQ​

ClassConstructor
ZmqStreamWriter(endpoint, queueSize=0, bind=true, delivery="reliable", serializer=nullptr)
ZmqStreamReader(endpoint, topic, queueSize=10, bind=false, delivery="reliable", serializer=nullptr); overload accepts std::vector<std::string> topics
ZmqRpcRequesterEndpoint plus serializer, identity, acknowledgement timeout, and optional schema
ZmqRpcResponderEndpoint plus serializer, bind mode, and optional schema

The publisher normally binds and subscribers connect. Set delivery="latest" for current-state streams where stale queued values are less useful than the newest one.

MQTT​

APIPurpose
MqttConnection(uri, clientId={}, options={})Constructs a shared broker connection. URI schemes are mqtt://, mqtts://, ws://, and wss://.
connect(timeoutSec=10.0) / disconnect()Establishes or closes the connection.
isConnected()Reports broker state.
publish(topic, data, size, qos=-1, retain=false)Publishes raw bytes; higher-level writers normally use it for you.
addSubscription(topicFilter, callback, qos=-1)Returns a SubscriptionHandle; supports + and # wildcards.
removeSubscription(topicFilter, handle)Removes a previously registered callback.
MqttStreamWriter / MqttStreamReaderStreaming over the shared connection with serializer, QoS, retain, and queue options.
MqttRpcRequester / MqttRpcResponderRPC by shared serviceName, with optional schema and serializer.
auto connection = std::make_shared<magpie::MqttConnection>(
"mqtts://broker.example.com:8883", "robot-01", options);
connection->connect();

magpie::MqttStreamWriter writer(connection);
magpie::StringFrame status("online");
writer.write(status, "robot/01/status");

writer.close();
connection->disconnect();

Share one std::shared_ptr<MqttConnection> between MQTT components. Close readers, writers, requesters, and responders before disconnecting it.

WebRTC​

APIPurpose
WebRtcConnectionOwns a separate WebRTC link for each remote peer.
connect(timeoutSec) / disconnect() / isConnected()Waits for the first peer, closes all links, or reports whether any peer is connected.
peerIds()Returns the IDs of currently connected remote peers.
WebRtcStreamWriter / WebRtcStreamReaderSends and receives frames by topic.
WebRtcRpcRequester / WebRtcRpcResponderCalls or exposes a peer service.
HttpSignaler, ZmqSignaler, MqttSignalerExchange offer, answer, and ICE messages.
WebRtcOptionsConfigures STUN/TURN, codecs, channel behavior, and role.

Set WebRtcOptions::role to "mesh" (default, connect every participant), "host" (accept clients), or "client" (connect to hosts, not other clients). Stream writes go to all connected peers; RPC replies return to the requesting peer. Multi-peer ZeroMQ signaling requires multiplex mode on every participant.

MAGPIE C++ currently carries media frames over the reliable WebRTC data channel. Set Python use_media_channels=False when interoperating with C++ so both peers agree on routing.

Value​

RPC and serializers use magpie::Value, a language-neutral variant for null, Boolean, signed integer, double, string, binary, list, and string-keyed dictionary data.

CreateRead
Value::null()type()
fromBool(v)asBool()
fromInt(v)asInt()
fromDouble(v)asDouble(); also accepts an integer value
fromString(v)asString()
fromBinary(v)asBinary()
fromList(v)asList()
fromDict(v)asDict()

An accessor throws std::runtime_error when the stored type is incompatible. Use Value::List and Value::Dict to build nested payloads.

Frames​

Frame supplies gid(), id(), name(), and timestamp() plus matching setters. Important methods are:

MethodPurpose
toDict(Dict& out) constWrites common and subclass fields into a wire dictionary.
loadFromDict(const Dict&)Populates a frame from wire data.
clone() constCreates an owning polymorphic copy for queues.
Frame::fromDict(const Dict&)Reconstructs a registered frame type; returns nullptr for an unknown type.
registerType(name, factory) / unregisterType(name)Controls the frame registry for custom types.

Built-in families include Boolean, integer, float, string, bytes, list, and dictionary frames plus optional raw/JPEG image and raw/FLAC audio frames. Readers return std::unique_ptr<Frame>; use dynamic_cast only after checking the expected type or protocol contract.

Schemas​

APIPurpose
BaseSchema::dispatch(request)Dispatches one decoded request and returns its response.
BaseSchema::wrap(method, params)Builds a requester-side envelope.
BaseSchema::unwrap(response)Extracts a result or throws a protocol error.
JsonRpcSchema::register_method(...)Registers a method, handler, description, and optional input/output schemas.
JsonRpcSchema::set_handler(name, handler)Attaches an implementation to a method already loaded from a contract.
JsonRpcSchema::from_json_file(path) / from_json_string(json)Builds a schema from shared JSON method definitions.
McpSchemaExtends JSON-RPC with MCP initialization, tool listing, tool calls, and ping.
auto schema = std::make_shared<magpie::McpSchema>("robot-service", "1.0.0");
schema->register_method(
"get_battery",
[](const magpie::Value::Dict&) {
return magpie::Value::fromDouble(0.82);
},
"Return the current battery level");

magpie::ZmqRpcResponder server("tcp://*:5556", nullptr, true, schema);
server.respond(1.0); // Schema dispatches the request.

Custom serializers​

MessagePack is the default. Implement Serializer to use another format:

class Serializer {
public:
virtual std::vector<std::uint8_t> serialize(const magpie::Value& value) = 0;
virtual magpie::Value deserialize(const std::uint8_t* data, std::size_t size) = 0;
};

Pass a shared serializer to matching transport endpoints. All peers on that path must use the same encoding and value conventions.

Ownership, errors, and shutdown​

  • Stream readers transfer frame ownership through std::unique_ptr<Frame>.
  • Connections, schemas, and serializers shared by several components use std::shared_ptr.
  • AckTimeoutError, ReplyTimeoutError, and TimeoutError distinguish RPC failure stages where supported.
  • JsonRpcError carries schema-level error information.
  • A timeout does not prove the remote operation did not execute; make retried commands idempotent.
  • Close child components before disconnecting their shared MQTT or WebRTC connection.

The public headers are the canonical signature reference. See the C++ examples for complete buildable programs.