C++
Connect directly to Foxglove or play back local data recorded with the C++ SDK.
Install the SDK
The C++ SDK is a wrapper around a C library. To build it, you will need to link that library and compile the SDK source as part of your build process. The SDK assumes C++17 or newer.
Download the library, source, and header files for your platform from the SDK release assets.
If you're using CMake, you can use the following as a starting point. For more detail, see the quickstart example.
cmake_minimum_required(VERSION 3.20)
# TODO: replace "my_program" throughout with the name of your project
project(my_program LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
# Fetch Foxglove SDK
include(FetchContent)
FetchContent_Declare(
foxglove
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
# TODO: Copy the URL and SHA for the appropriate .zip file from here:
# https://github.com/foxglove/foxglove-sdk/releases?q=sdk%2F&expanded=true
URL <download URL from the GitHub release>
URL_HASH SHA256=<sha from the GitHub release>
)
FetchContent_MakeAvailable(foxglove)
# Assuming the project consists of a single source file, main.cpp
add_executable(my_program main.cpp)
# Add include directory for Foxglove SDK
target_include_directories(my_program PRIVATE ${foxglove_SOURCE_DIR}/include)
target_include_directories(my_program PRIVATE ${foxglove_SOURCE_DIR}/include/foxglove)
# Find all Foxglove SDK source files
file(GLOB FOXGLOVE_SOURCES CONFIGURE_DEPENDS
"${foxglove_SOURCE_DIR}/src/*.cpp"
"${foxglove_SOURCE_DIR}/src/server/*.cpp"
)
# Add Foxglove SDK source files
target_sources(my_program PRIVATE ${FOXGLOVE_SOURCES})
# Link against libfoxglove.a
target_link_libraries(my_program PRIVATE ${foxglove_SOURCE_DIR}/lib/libfoxglove.a)
Live data
Log messages from C++
#include <foxglove/foxglove.hpp>
#include <foxglove/server.hpp>
#include <chrono>
#include <csignal>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
int main(int argc, const char *argv[]) {
foxglove::WebSocketServerOptions options;
auto serverResult = foxglove::WebSocketServer::create(std::move(options));
if (!serverResult.has_value()) {
std::cerr << foxglove::strerror(serverResult.error()) << '\n';
return 1;
}
auto server = std::move(serverResult.value());
auto channel = foxglove::RawChannel::create("/hello", "json").value();
auto start = std::chrono::steady_clock::now();
// Log until interrupted
static std::function<void()> sigint_handler;
std::atomic_bool done = false;
sigint_handler = [&] { done = true; };
std::signal(SIGINT, [](int) {
if (sigint_handler) {
sigint_handler();
}
});
while (!done) {
auto dur = std::chrono::steady_clock::now() - start;
float elapsed_seconds = std::chrono::duration<float>(dur).count();
std::string msg = "{\"elapsed\": " + std::to_string(elapsed_seconds) + "}";
channel.log(reinterpret_cast<const std::byte *>(msg.data()), msg.size());
std::this_thread::sleep_for(33ms);
}
return 0;
}
Run the example
If you're using something like the CMake configuration above, you can create a build
directory and
run the following.
cd build
cmake ..
cmake --build .
./my_program
Connect
In Foxglove, select "Open connection" from the dashboard or left-hand menu.
Select "Foxglove WebSocket" in the "Open a new connection" dialog, then click "Open" to accept the default connection string:
Local data
Recording data to a file
The SDK can also log data to disk. Let's augment the example above to also produce an MCAP file which can later be opened in Foxglove:
#include <foxglove/foxglove.hpp>
#include <foxglove/mcap.hpp>
#include <foxglove/server.hpp>
#include <chrono>
#include <csignal>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
int main(int argc, const char *argv[]) {
foxglove::WebSocketServerOptions options;
auto serverResult = foxglove::WebSocketServer::create(std::move(options));
if (!serverResult.has_value()) {
std::cerr << foxglove::strerror(serverResult.error()) << '\n';
return 1;
}
auto server = std::move(serverResult.value());
auto channel = foxglove::RawChannel::create("/hello", "json").value();
auto start = std::chrono::steady_clock::now();
foxglove::McapWriterOptions mcap_options;
mcap_options.path = "example.mcap";
auto writerResult = foxglove::McapWriter::create(mcap_options);
if (!writerResult.has_value()) {
std::cerr << foxglove::strerror(writerResult.error()) << '\n';
return 1;
}
// Keep a reference to the writer. It will be closed when the writer is
// destroyed, or we could call `.close()` to close it manually.
auto writer = std::move(writerResult.value());
// Log until interrupted
static std::function<void()> sigint_handler;
std::atomic_bool done = false;
sigint_handler = [&] { done = true; };
std::signal(SIGINT, [](int) {
if (sigint_handler) {
sigint_handler();
}
});
while (!done) {
auto dur = std::chrono::steady_clock::now() - start;
float elapsed_seconds = std::chrono::duration<float>(dur).count();
std::string msg = "{\"elapsed\": " + std::to_string(elapsed_seconds) + "}";
channel.log(reinterpret_cast<const std::byte *>(msg.data()), msg.size());
std::this_thread::sleep_for(33ms);
}
return 0;
}
Viewing data from a file
To load local files for visualization, you can:
- Click "Open local file(s)…" in the dashboard or left-hand menu
- Open or drag-and-drop the files from your OS file manager (desktop only)
When opening multiple files, Foxglove will merge the data into a single playback timeline.
You can only merge multiple files of the same format.
Imported data
After importing data to Foxglove, select individual resources to visualize on the Recordings or Events pages:

Select a custom time range of data (can span multiple recordings or events) to visualize on the Timeline page:
Links and resources
- SDK documentation with a more detailed example
- C++ reference
- Source code