nros C++ API
Lightweight ROS 2 client for embedded real-time systems (C++ headers)
Loading...
Searching...
No Matches
publisher.hpp
Go to the documentation of this file.
1// nros-cpp: Publisher class
2// Freestanding C++ — no exceptions, no STL required
3
10#ifndef NROS_CPP_PUBLISHER_HPP
11#define NROS_CPP_PUBLISHER_HPP
12
13#include <cstdint>
14#include <cstddef>
15#include <string.h> // memcpy — `<cstring>` isn't in Zephyr's minimal libcpp
16
17#include "nros/config.hpp"
18#include "nros/result.hpp"
19
20#include "nros_cpp_ffi.h"
21
22namespace nros {
23
26static constexpr size_t PUBLISHER_TOPIC_NAME_MAX = 256;
27
46template <typename M> class Publisher {
47 public:
52 Result publish(const M& msg) { return Result(M::ffi_publish(storage_, &msg)); }
53
55 Result publish_raw(const uint8_t* data, size_t len) {
56 if (!initialized_) return Result(ErrorCode::NotInitialized);
57 return Result(nros_cpp_publish_raw(storage_, data, len));
58 }
59
70 template <typename W> Result publish_streamed(size_t total_len, W&& writer) {
71 if (!initialized_) return Result(ErrorCode::NotInitialized);
72 struct Ctx {
73 W writer;
74 size_t total;
75 } ctx{static_cast<W&&>(writer), total_len};
76 auto size_cb = [](size_t* out_total, void* user) {
77 auto* c = static_cast<Ctx*>(user);
78 *out_total = c->total;
79 };
80 auto chunk_cb = [](uint8_t* out_buf, size_t cap, size_t* out_written, void* user) {
81 auto* c = static_cast<Ctx*>(user);
82 *out_written = c->writer(out_buf, cap);
83 };
85 static_cast<void*>(&ctx)));
86 }
87
88 // ====================================================================
89 // Phase 124.A.7 — zero-copy publish (loan / commit / discard)
90 // ====================================================================
91
95 class Loan {
96 public:
97 Loan() : pub_(nullptr), buf_(nullptr), cap_(0), token_(nullptr) {}
98 Loan(Loan&& o) : pub_(o.pub_), buf_(o.buf_), cap_(o.cap_), token_(o.token_) {
99 o.pub_ = nullptr;
100 o.token_ = nullptr;
101 }
103 if (this != &o) {
104 release();
105 pub_ = o.pub_;
106 buf_ = o.buf_;
107 cap_ = o.cap_;
108 token_ = o.token_;
109 o.pub_ = nullptr;
110 o.token_ = nullptr;
111 }
112 return *this;
113 }
114 Loan(const Loan&) = delete;
115 Loan& operator=(const Loan&) = delete;
116 ~Loan() { release(); }
117
119 uint8_t* data() { return buf_; }
120 const uint8_t* data() const { return buf_; }
121 size_t capacity() const { return cap_; }
122
123 bool is_valid() const { return token_ != nullptr; }
124
127 if (!token_) return Result(ErrorCode::NotInitialized);
129 pub_ = nullptr;
130 token_ = nullptr;
131 buf_ = nullptr;
132 cap_ = 0;
133 return Result(ret);
134 }
135
138 if (!token_) return Result::success();
140 pub_ = nullptr;
141 token_ = nullptr;
142 buf_ = nullptr;
143 cap_ = 0;
144 return Result(ret);
145 }
146
149 Loan(void* pub, uint8_t* buf, size_t cap, void* token)
150 : pub_(pub), buf_(buf), cap_(cap), token_(token) {}
151
152 private:
153 void release() {
154 if (token_ && pub_) {
155 nros_cpp_publisher_discard(pub_, token_);
156 token_ = nullptr;
157 }
158 }
159
160 void* pub_;
161 uint8_t* buf_;
162 size_t cap_;
163 void* token_;
164 };
165
170 if (!initialized_) return Expected<Loan>::error(Result(ErrorCode::NotInitialized));
171 uint8_t* buf = nullptr;
172 size_t cap = 0;
173 void* token = nullptr;
175 if (ret != 0) return Expected<Loan>::error(Result(ret));
176 return Expected<Loan>::ok(Loan{storage_, buf, cap, token});
177 }
178
180 const char* get_topic_name() const { return initialized_ ? topic_name_ : ""; }
181
183 bool is_valid() const { return initialized_; }
184
187 if (initialized_) {
189 initialized_ = false;
190 }
191 }
192
193 // Move semantics (non-copyable). Relocation goes through the
194 // `nros_cpp_publisher_relocate` runtime call.
195 Publisher(Publisher&& other) : initialized_(other.initialized_) {
196 if (other.initialized_) {
197 nros_cpp_publisher_relocate(other.storage_, storage_);
198 ::memcpy(topic_name_, other.topic_name_, sizeof(topic_name_));
199 other.initialized_ = false;
200 }
201 }
202
204 if (this != &other) {
205 if (initialized_) {
207 initialized_ = false;
208 }
209 if (other.initialized_) {
210 nros_cpp_publisher_relocate(other.storage_, storage_);
211 ::memcpy(topic_name_, other.topic_name_, sizeof(topic_name_));
212 initialized_ = true;
213 other.initialized_ = false;
214 }
215 }
216 return *this;
217 }
218
221 Publisher() : storage_(), topic_name_{}, initialized_(false) {}
222
223 // ====================================================================
224 // Phase 108 — status events
225 // ====================================================================
226
232
236 void* user_context = nullptr) {
237 if (!initialized_) return Result(ErrorCode::NotInitialized);
238 return Result(nros_cpp_publisher_set_offered_deadline_missed(storage_, deadline_ms, cb,
239 user_context));
240 }
241
246 if (!initialized_) return Result(ErrorCode::NotInitialized);
248 }
249
250 private:
251 Publisher(const Publisher&) = delete;
252 Publisher& operator=(const Publisher&) = delete;
253
254 friend class Node;
255
256 alignas(8) uint8_t storage_[NROS_PUBLISHER_SIZE];
257 char topic_name_[PUBLISHER_TOPIC_NAME_MAX];
258 bool initialized_;
259};
260
261} // namespace nros
262
263// Phase 84.G8: out-of-line definition of Node::create_publisher<M>().
264// Placed here so consumers only pay for this template when they actually
265// use publishers — including `nros/node.hpp` alone no longer drags in
266// every entity's code path.
267#include "nros/node.hpp"
268
269namespace nros {
270
271template <typename M>
273 if (!initialized_) return Result(ErrorCode::NotInitialized);
275 ffi_qos.reliability = static_cast<nros_cpp_qos_reliability_t>(qos.reliability_raw());
276 ffi_qos.durability = static_cast<nros_cpp_qos_durability_t>(qos.durability_raw());
277 ffi_qos.history = static_cast<nros_cpp_qos_history_t>(qos.history_raw());
278 ffi_qos.liveliness_kind = static_cast<nros_cpp_qos_liveliness_t>(qos.liveliness_raw());
279 ffi_qos.depth = qos.depth();
280 ffi_qos.deadline_ms = qos.deadline_ms();
281 ffi_qos.lifespan_ms = qos.lifespan_ms();
282 ffi_qos.liveliness_lease_ms = qos.liveliness_lease_ms();
283 ffi_qos.avoid_ros_namespace_conventions = qos.avoid_ros_namespace_conventions() ? 1 : 0;
284 nros_cpp_ret_t ret = nros_cpp_publisher_create(&handle_, topic, M::TYPE_NAME, M::TYPE_HASH,
285 ffi_qos, out.storage_);
286 if (ret == 0) {
287 // Topic name lives C++-side; copy + null-terminate into the
288 // fixed-size buffer. Truncation is silent.
289 size_t topic_len = 0;
290 while (topic[topic_len] != '\0' && topic_len + 1 < sizeof(out.topic_name_)) {
291 out.topic_name_[topic_len] = topic[topic_len];
292 ++topic_len;
293 }
294 out.topic_name_[topic_len] = '\0';
295 out.initialized_ = true;
296 }
297 return Result(ret);
298}
299
305template <typename M>
307 const PublisherOptions& options) {
308 (void)options; // reserved — no live fields today
310}
311
317template <typename M>
318inline Expected<Publisher<M>> make_publisher(Node& node, const char* topic,
319 const QoS& qos = QoS::default_profile()) {
321 Result r = node.create_publisher<M>(p, topic, qos);
322 if (!r.ok()) return Expected<Publisher<M>>::error(r);
323 return Expected<Publisher<M>>::ok(std::move(p));
324}
325
326} // namespace nros
327
328#endif // NROS_CPP_PUBLISHER_HPP
Definition result.hpp:160
ErrorCode error() const
Definition result.hpp:183
bool ok() const
Definition result.hpp:176
Definition future.hpp:40
Definition node.hpp:158
Result create_publisher(Publisher< M > &out, const char *topic, const QoS &qos=QoS::default_profile())
Definition publisher.hpp:272
Definition publisher.hpp:95
Result commit(size_t actual_len)
Send actual_len bytes. Consumes the loan.
Definition publisher.hpp:126
Loan(Loan &&o)
Definition publisher.hpp:98
Loan(void *pub, uint8_t *buf, size_t cap, void *token)
Definition publisher.hpp:149
const uint8_t * data() const
Definition publisher.hpp:120
~Loan()
Definition publisher.hpp:116
Loan()
Definition publisher.hpp:97
Loan & operator=(const Loan &)=delete
size_t capacity() const
Definition publisher.hpp:121
Loan & operator=(Loan &&o)
Definition publisher.hpp:102
Result discard()
Abandon without sending. Consumes the loan.
Definition publisher.hpp:137
Loan(const Loan &)=delete
bool is_valid() const
Definition publisher.hpp:123
uint8_t * data()
Writable view of the loaned bytes.
Definition publisher.hpp:119
Definition publisher.hpp:46
Expected< Loan > loan(size_t requested_len)
Definition publisher.hpp:169
Result publish_streamed(size_t total_len, W &&writer)
Definition publisher.hpp:70
Publisher()
Definition publisher.hpp:221
Result publish_raw(const uint8_t *data, size_t len)
Publish raw CDR bytes.
Definition publisher.hpp:55
const char * get_topic_name() const
Get the topic name.
Definition publisher.hpp:180
Result on_liveliness_lost(nros_cpp_publisher_count_cb_t cb, void *user_context=nullptr)
Register a callback for liveliness-lost events on this publisher.
Definition publisher.hpp:228
Publisher(Publisher &&other)
Definition publisher.hpp:195
Result publish(const M &msg)
Definition publisher.hpp:52
~Publisher()
Destructor — releases publisher resources.
Definition publisher.hpp:186
Result on_offered_deadline_missed(uint32_t deadline_ms, nros_cpp_publisher_count_cb_t cb, void *user_context=nullptr)
Definition publisher.hpp:235
bool is_valid() const
Check if the publisher is initialized and valid.
Definition publisher.hpp:183
Result assert_liveliness()
Definition publisher.hpp:245
Publisher & operator=(Publisher &&other)
Definition publisher.hpp:203
Definition qos.hpp:67
static constexpr QoS default_profile()
Default profile: RELIABLE + VOLATILE + KEEP_LAST(10).
Definition qos.hpp:160
Definition result.hpp:52
static constexpr Result success()
Named constructors.
Definition result.hpp:74
Inline storage-size macros for opaque entity buffers.
int nros_cpp_ret_t
Definition future.hpp:20
Definition nros.hpp:42
static constexpr size_t PUBLISHER_TOPIC_NAME_MAX
Definition publisher.hpp:26
bool ok()
Check if the nros session is initialized.
Definition node.hpp:717
nros::Node and global session helpers.
nros_cpp_qos_history_t
Definition qos.hpp:31
nros_cpp_qos_liveliness_t
Definition qos.hpp:35
nros_cpp_qos_durability_t
Definition qos.hpp:27
nros_cpp_qos_reliability_t
Definition qos.hpp:23
nros::Result, nros::ErrorCode, and the NROS_TRY macro.
Definition qos.hpp:41