C++ SDK (WIP)
The C++ SDK, a CXX bridge over the Rust SDK, and how to build it from source with Bazel.
The Iggy C++ SDK wraps the Rust SDK through a CXX FFI bridge, so it can use all transport protocols (TCP, QUIC, HTTP, WebSocket) via connection strings. The source code is available at github.com/apache/iggy/tree/master/foreign/cpp.
This SDK isn't published to any package registry. Consume it from the monorepo and build it from source with Bazel.
Building from source
The project builds with the Bazel version pinned in .bazelversion (BUILD.bazel / MODULE.bazel). Its Rust bridge uses the Cargo and Rust toolchain provisioned by rules_rust, with a separate target directory in the Bazel output tree. Use a compatible Java runtime for Bazel; the pinned Bazel 9.2.0 requires Java 21 or newer.
cd foreign/cpp
# Build the library
bazel build //:iggy-cpp
# Unit tests
bazel test //:unit
# Low-level integration tests (require a running server)
bazel test //:e2eQuick start
The snippet below mirrors the SDK's own end-to-end tests in foreign/cpp/tests/e2e. Start a local server on 127.0.0.1:8090 with the iggy/iggy credentials first. The stream name must not already exist.
#include "lib.rs.h"
#include <cstdint>
#include <iostream>
#include <string>
#include <utility>
iggy::ffi::Identifier id(const std::string &name) {
iggy::ffi::Identifier identifier;
identifier.set_string(name);
return identifier;
}
iggy::ffi::Identifier numeric_id(const std::uint32_t value) {
iggy::ffi::Identifier identifier;
identifier.set_numeric(value);
return identifier;
}
rust::Vec<std::uint8_t> payload(const std::string &text) {
rust::Vec<std::uint8_t> bytes;
for (const char c : text) {
bytes.push_back(static_cast<std::uint8_t>(c));
}
return bytes;
}
int main() {
iggy::ffi::Client *client = iggy::ffi::new_connection({});
client->connect();
client->login_user("iggy", "iggy");
client->create_stream("my-stream");
// (stream, name, partitions, compression, expiry kind, expiry value,
// max topic size, extra options)
client->create_topic(id("my-stream"), "my-topic", 1, "none",
"server_default", 0, "server_default", {});
rust::Vec<iggy::ffi::IggyMessageToSend> messages;
for (int i = 0; i < 10; i++) {
messages.push_back(iggy::ffi::make_message(
payload("message-" + std::to_string(i)), {}));
}
client->send_messages(id("my-stream"), id("my-topic"), "balanced", {},
std::move(messages));
// Partition ids are 0-based: 0 is the first partition.
auto polled = client->poll_messages(id("my-stream"), id("my-topic"), 0,
"consumer", numeric_id(1),
"offset", 0, 10, false);
for (const auto &message : polled.messages) {
std::string text(message.payload.begin(), message.payload.end());
std::cout << "Offset: " << message.offset << ", Payload: " << text
<< std::endl;
}
iggy::ffi::delete_client(client);
return 0;
}Polling strategies are selected by kind string: offset, timestamp, first, last, or next. Partitioning kinds for sending are balanced, partition_id, and messages_key.
Connection strings
The C++ SDK supports the same connection string format as the Rust SDK:
iggy://user:pass@host:port (TCP, default)
iggy+quic://user:pass@host:port (QUIC)
iggy+http://user:pass@host:port (HTTP)
iggy+ws://user:pass@host:port (WebSocket)iggy::ffi::from_connection_string() accepts these strings. new_connection() instead takes an IggyClientConfig: {} selects TCP at 127.0.0.1:8090 without automatic login, and its server_address field overrides that address. Binary clients authenticate from their connection string during connect(); HTTP requires an explicit login_user() call. See connection strings for the supported options and credential syntax.
Helper types
Beyond the generated lib.rs.h FFI surface, foreign/cpp/include/iggy.hpp ships typed C++ helpers: CompressionAlgorithm, MaxTopicSize, Expiry, PollingStrategy, IdKind, TopicOption, SnapshotCompression, and SystemSnapshotType, plus the IggyException error type. They construct and validate the kind strings and values the raw FFI calls expect.
Current status
The FFI bridge exposes command-level operations for streams, topics, partitions, and segments; message sending and polling with user headers; consumer groups and consumer offsets; stats, client info, and cluster metadata; snapshots; user create/get/update/delete, permission updates and password changes; topic option discovery (describe_options); and raw binary requests (send_binary_request).
Not yet exposed: the high-level Producer/Consumer wrappers and personal access token management. Contributions are welcome.
