nros C API
Lightweight ROS 2 client for embedded real-time systems
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
nros_generated.h File Reference
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "rclc/visibility_control.h"
#include "rclc/detail/nros_config_generated.h"
Include dependency graph for nros_generated.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ActionClientInternal
 
struct  ActionServerInternal
 
struct  nros_transport_ops_t
 
struct  rcl_action_client_options_t
 
struct  rcl_action_client_t
 
struct  rcl_action_server_options_t
 
struct  rcl_action_server_t
 
struct  rcl_allocator_t
 
struct  rcl_client_options_t
 
struct  rcl_client_t
 
struct  rcl_clock_t
 
struct  rcl_context_t
 
struct  rcl_duration_t
 
struct  rcl_guard_condition_t
 
struct  rcl_lifecycle_state_machine_t
 
struct  rcl_node_options_t
 
struct  rcl_node_t
 
struct  rcl_publisher_options_t
 
struct  rcl_publisher_t
 
struct  rcl_service_options_t
 
struct  rcl_service_t
 
struct  rcl_subscription_options_t
 
struct  rcl_subscription_t
 
struct  rcl_timer_t
 
struct  rclc_action_endpoint_hashes_t
 
struct  rclc_action_type_t
 
struct  rclc_count_status_t
 
struct  rclc_endpoint_info_t
 
struct  rclc_executor_t
 
struct  rclc_executor_trigger_handle_t
 
struct  rclc_goal_handle_t
 
struct  rclc_goal_uuid_t
 
struct  rclc_integrity_status_t
 
struct  rclc_liveliness_changed_status_t
 
struct  rclc_message_type_t
 
struct  rclc_node_ref_t
 
struct  rclc_polling_action_client_t
 
struct  rclc_polling_action_server_t
 
struct  rclc_polling_client_t
 
struct  rclc_polling_service_t
 
struct  rclc_polling_subscription_t
 
struct  rclc_qos_override_t
 
struct  rclc_qos_t
 
struct  rclc_sched_context_t
 
struct  rclc_service_type_t
 
struct  rclc_support_t
 
struct  rclc_time_t
 
struct  rclc_wake_state_t
 
struct  ServiceClientInternal
 
struct  ServiceServerInternal
 

Macros

#define MAX_RMW_NAME_LEN   32
 
#define NROS_DOMAIN_ID_EXPLICIT_ZERO   255
 
#define NROS_DOMAIN_ID_INHERIT   UINT32_MAX
 
#define NROS_GENERATED_H
 
#define NROS_MAX_ACTION_NAME_LEN   256
 
#define NROS_MAX_CONCURRENT_GOALS   4
 
#define NROS_MAX_LOCATOR_LEN   128
 
#define NROS_MAX_NAME_LEN   64
 
#define NROS_MAX_NAMESPACE_LEN   128
 
#define NROS_MAX_SERVICE_NAME_LEN   256
 
#define NROS_MAX_TOPIC_LEN   256
 
#define NROS_MAX_TYPE_HASH_LEN   128
 
#define NROS_MAX_TYPE_NAME_LEN   256
 
#define NROS_PUBLISHER_GID_SIZE   24
 
#define NROS_SERIALIZATION_FORMAT_ID   1
 
#define RCL_RET_ERROR   -1
 
#define RCL_RET_INVALID_ARGUMENT   -3
 
#define RCL_RET_NOT_INIT   -7
 
#define RCL_RET_OK   0
 
#define RCL_RET_TIMEOUT   -2
 
#define RCL_RET_UNSUPPORTED   -16
 
#define RCLC_LIFECYCLE_RET_ERROR   2
 
#define RCLC_LIFECYCLE_RET_FAILURE   1
 
#define RCLC_LIFECYCLE_RET_OK   0
 
#define RCLC_LIFECYCLE_STATE_ACTIVE   3
 
#define RCLC_LIFECYCLE_STATE_ERROR_PROCESSING   5
 
#define RCLC_LIFECYCLE_STATE_FINALIZED   4
 
#define RCLC_LIFECYCLE_STATE_INACTIVE   2
 
#define RCLC_LIFECYCLE_STATE_UNCONFIGURED   1
 
#define RCLC_LIFECYCLE_TRANSITION_ACTIVATE   3
 
#define RCLC_LIFECYCLE_TRANSITION_CLEANUP   2
 
#define RCLC_LIFECYCLE_TRANSITION_CONFIGURE   1
 
#define RCLC_LIFECYCLE_TRANSITION_DEACTIVATE   4
 
#define RCLC_LIFECYCLE_TRANSITION_ERROR_RECOVERY   60
 
#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_ACTIVE   7
 
#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_INACTIVE   6
 
#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_UNCONFIGURED   5
 
#define RCLC_RET_ALREADY_EXISTS   -5
 
#define RCLC_RET_BAD_SEQUENCE   -8
 
#define RCLC_RET_FULL   -6
 
#define RCLC_RET_NOT_ALLOWED   -12
 
#define RCLC_RET_NOT_FOUND   -4
 
#define RCLC_RET_PUBLISH_FAILED   -10
 
#define RCLC_RET_REENTRANT   -15
 
#define RCLC_RET_REJECTED   -13
 
#define RCLC_RET_SERVICE_FAILED   -9
 
#define RCLC_RET_STALE_NODE   -17
 
#define RCLC_RET_SUBSCRIPTION_FAILED   -11
 
#define RCLC_RET_TRY_AGAIN   -14
 
#define RCLC_SERVICE_TYPED_ERR_NO_CALLBACK   -5
 
#define RCLC_SERVICE_TYPED_ERR_REQUEST_DESERIALIZE   -1
 
#define RCLC_SERVICE_TYPED_ERR_REQUEST_SERIALIZE   -3
 
#define RCLC_SERVICE_TYPED_ERR_RESPONSE_DESERIALIZE   -4
 
#define RCLC_SERVICE_TYPED_ERR_RESPONSE_SERIALIZE   -2
 
#define RCLC_SERVICE_TYPED_OK   0
 
#define RCLC_SHUTDOWN_CALLBACK_HANDLE_INVALID   4294967295
 

Typedefs

typedef int rcl_ret_t
 
typedef void(* rclc_accepted_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, void *context)
 
typedef enum rclc_cancel_response_t(* rclc_cancel_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, void *context)
 
typedef uint8_t rclc_deadline_policy_t
 
typedef bool(* rclc_endpoint_info_visit_fn) (void *ctx, const struct rclc_endpoint_info_t *info)
 
typedef void(* rclc_event_liveliness_changed_cb_t) (struct rcl_subscription_t *sub, struct rclc_liveliness_changed_status_t status, void *user_context)
 
typedef void(* rclc_event_publisher_count_cb_t) (struct rcl_publisher_t *pub_, struct rclc_count_status_t status, void *user_context)
 
typedef void(* rclc_event_subscriber_count_cb_t) (struct rcl_subscription_t *sub, struct rclc_count_status_t status, void *user_context)
 
typedef bool(* rclc_executor_trigger_t) (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
typedef void(* rclc_feedback_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, const uint8_t *feedback, size_t feedback_len, void *context)
 
typedef enum rclc_goal_response_t(* rclc_goal_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *goal_request, size_t goal_len, void *context)
 
typedef void(* rclc_goal_response_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, bool accepted, void *context)
 
typedef void(* rclc_guard_condition_callback_t) (void *context)
 
typedef uint8_t(* rclc_lifecycle_callback_t) (void *context)
 
typedef int32_t(* rclc_message_deserialize_fn_t) (const uint8_t *buffer, size_t len, void *msg)
 
typedef int32_t(* rclc_message_serialize_fn_t) (const void *msg, uint8_t *buffer, size_t capacity, size_t *out_len)
 
typedef bool(* rclc_names_and_types_visit_fn) (void *ctx, const char *name, const char *const *types, size_t types_count)
 
typedef bool(* rclc_node_visit_fn) (void *ctx, const char *node_name, const char *node_namespace, const char *enclave)
 
typedef void(* rclc_response_callback_t) (const uint8_t *response, size_t response_len, void *context)
 
typedef void(* rclc_result_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, enum rclc_goal_status_t status, const uint8_t *result, size_t result_len, void *context)
 
typedef uint8_t rclc_sched_class_t
 
typedef uint8_t rclc_sched_context_id_t
 
typedef uint8_t rclc_sched_priority_t
 
typedef bool(* rclc_service_raw_callback_t) (const uint8_t *request_data, size_t request_len, uint8_t *response_data, size_t response_capacity, size_t *response_len, void *context)
 
typedef uint32_t rclc_shutdown_callback_handle_t
 
typedef void(* rclc_shutdown_callback_t) (void *context)
 
typedef void(* rclc_subscription_callback_with_context_t) (const void *msg, void *context)
 
typedef void(* rclc_subscription_info_callback_t) (const uint8_t *data, size_t len, const uint8_t *attachment, size_t attachment_len, void *context)
 
typedef void(* rclc_subscription_raw_callback_t) (const uint8_t *data, size_t len, void *context)
 
typedef void(* rclc_subscription_validated_callback_t) (const uint8_t *data, size_t len, int64_t gap, bool duplicate, int8_t crc_valid, void *context)
 
typedef void(* rclc_timer_callback_with_context_t) (struct rcl_timer_t *timer, void *context)
 
typedef struct rmw_publisher_allocation_t rmw_publisher_allocation_t
 
typedef struct rmw_subscription_allocation_t rmw_subscription_allocation_t
 

Enumerations

enum  rcl_clock_type_t { RCL_CLOCK_UNINITIALIZED = 0 , RCL_ROS_TIME = 1 , RCL_SYSTEM_TIME = 2 , RCL_STEADY_TIME = 3 }
 
enum  rclc_action_client_state_t { RCLC_ACTION_CLIENT_STATE_UNINITIALIZED = 0 , RCLC_ACTION_CLIENT_STATE_INITIALIZED = 1 , RCLC_ACTION_CLIENT_STATE_SHUTDOWN = 2 }
 
enum  rclc_action_server_state_t { RCLC_ACTION_SERVER_STATE_UNINITIALIZED = 0 , RCLC_ACTION_SERVER_STATE_INITIALIZED = 1 , RCLC_ACTION_SERVER_STATE_SHUTDOWN = 2 }
 
enum  rclc_cancel_response_t { RCLC_CANCEL_REJECT = 0 , RCLC_CANCEL_ACCEPT = 1 }
 
enum  rclc_cancel_return_code_t { RCLC_CANCEL_RC_OK = 0 , RCLC_CANCEL_RC_REJECTED = 1 , RCLC_CANCEL_RC_UNKNOWN_GOAL = 2 , RCLC_CANCEL_RC_GOAL_TERMINATED = 3 }
 
enum  rclc_client_state_t { RCLC_CLIENT_STATE_UNINITIALIZED = 0 , RCLC_CLIENT_STATE_INITIALIZED = 1 , RCLC_CLIENT_STATE_REGISTERED = 2 , RCLC_CLIENT_STATE_SHUTDOWN = 3 }
 
enum  rclc_clock_state_t { RCLC_CLOCK_STATE_UNINITIALIZED = 0 , RCLC_CLOCK_STATE_READY = 1 , RCLC_CLOCK_STATE_SHUTDOWN = 2 }
 
enum  rclc_deadline_policy_t { RCLC_DEADLINE_POLICY_RELEASED = 0 , RCLC_DEADLINE_POLICY_ACTIVATED = 1 , RCLC_DEADLINE_POLICY_INHERITED = 2 }
 
enum  rclc_executor_handle_invocation_t { ON_NEW_DATA = 0 , ALWAYS = 1 }
 
enum  rclc_executor_semantics_t { RCLCPP_EXECUTOR = 0 , LET = 1 }
 
enum  rclc_executor_state_t { RCLC_EXECUTOR_STATE_UNINITIALIZED = 0 , RCLC_EXECUTOR_STATE_INITIALIZED = 1 , RCLC_EXECUTOR_STATE_SPINNING = 2 , RCLC_EXECUTOR_STATE_SHUTDOWN = 3 }
 
enum  rclc_goal_response_t { RCLC_GOAL_REJECT = 0 , RCLC_GOAL_ACCEPT_AND_EXECUTE = 1 , RCLC_GOAL_ACCEPT_AND_DEFER = 2 }
 
enum  rclc_goal_status_t {
  RCLC_GOAL_STATUS_UNKNOWN = 0 , RCLC_GOAL_STATUS_ACCEPTED = 1 , RCLC_GOAL_STATUS_EXECUTING = 2 , RCLC_GOAL_STATUS_CANCELING = 3 ,
  RCLC_GOAL_STATUS_SUCCEEDED = 4 , RCLC_GOAL_STATUS_CANCELED = 5 , RCLC_GOAL_STATUS_ABORTED = 6
}
 
enum  rclc_guard_condition_state_t { RCLC_GUARD_CONDITION_STATE_UNINITIALIZED = 0 , RCLC_GUARD_CONDITION_STATE_INITIALIZED = 1 , RCLC_GUARD_CONDITION_STATE_SHUTDOWN = 2 }
 
enum  rclc_node_state_t { RCLC_NODE_STATE_UNINITIALIZED = 0 , RCLC_NODE_STATE_INITIALIZED = 1 , RCLC_NODE_STATE_SHUTDOWN = 2 }
 
enum  rclc_publisher_state_t { RCLC_PUBLISHER_STATE_UNINITIALIZED = 0 , RCLC_PUBLISHER_STATE_INITIALIZED = 1 , RCLC_PUBLISHER_STATE_SHUTDOWN = 2 }
 
enum  rclc_qos_durability_t { RCLC_QOS_DURABILITY_VOLATILE = 0 , RCLC_QOS_DURABILITY_TRANSIENT_LOCAL = 1 , RCLC_QOS_DURABILITY_SYSTEM_DEFAULT = 2 , RCLC_QOS_DURABILITY_UNKNOWN = 3 }
 
enum  rclc_qos_history_t { RCLC_QOS_HISTORY_KEEP_LAST = 0 , RCLC_QOS_HISTORY_KEEP_ALL = 1 , RCLC_QOS_HISTORY_SYSTEM_DEFAULT = 2 , RCLC_QOS_HISTORY_UNKNOWN = 3 }
 
enum  rclc_qos_liveliness_t {
  RCLC_QOS_LIVELINESS_NONE = 0 , RCLC_QOS_LIVELINESS_AUTOMATIC = 1 , RCLC_QOS_LIVELINESS_MANUAL_BY_TOPIC = 2 , RCLC_QOS_LIVELINESS_MANUAL_BY_NODE = 3 ,
  RCLC_QOS_LIVELINESS_UNKNOWN = 4
}
 
enum  rclc_qos_reliability_t { RCLC_QOS_RELIABILITY_BEST_EFFORT = 0 , RCLC_QOS_RELIABILITY_RELIABLE = 1 , RCLC_QOS_RELIABILITY_SYSTEM_DEFAULT = 2 , RCLC_QOS_RELIABILITY_UNKNOWN = 3 }
 
enum  rclc_sched_class_t {
  RCLC_SCHED_CLASS_FIFO = 0 , RCLC_SCHED_CLASS_EDF = 1 , RCLC_SCHED_CLASS_SPORADIC = 2 , RCLC_SCHED_CLASS_BEST_EFFORT = 3 ,
  RCLC_SCHED_CLASS_TIME_TRIGGERED = 4
}
 
enum  rclc_sched_priority_t { RCLC_SCHED_PRIORITY_CRITICAL = 0 , RCLC_SCHED_PRIORITY_NORMAL = 1 , RCLC_SCHED_PRIORITY_BEST_EFFORT = 2 }
 
enum  rclc_service_state_t { RCLC_SERVICE_STATE_UNINITIALIZED = 0 , RCLC_SERVICE_STATE_INITIALIZED = 1 , RCLC_SERVICE_STATE_SHUTDOWN = 2 }
 
enum  rclc_subscription_state_t { RCLC_SUBSCRIPTION_STATE_UNINITIALIZED = 0 , RCLC_SUBSCRIPTION_STATE_INITIALIZED = 1 , RCLC_SUBSCRIPTION_STATE_SHUTDOWN = 2 }
 
enum  rclc_support_state_t { RCLC_SUPPORT_STATE_UNINITIALIZED = 0 , RCLC_SUPPORT_STATE_INITIALIZED = 1 , RCLC_SUPPORT_STATE_SHUTDOWN = 2 }
 
enum  rclc_timer_state_t { RCLC_TIMER_STATE_UNINITIALIZED = 0 , RCLC_TIMER_STATE_RUNNING = 1 , RCLC_TIMER_STATE_CANCELED = 2 , RCLC_TIMER_STATE_SHUTDOWN = 3 }
 

Functions

rcl_ret_t nros_c_support_init_baked (struct rclc_support_t *support, int argc, const char *const *argv, const struct rcl_allocator_t *allocator, const char *rmw, const char *locator, uint8_t domain_id)
 
uint64_t nros_platform_clock_ns (void)
 
uint32_t nros_platform_critical_section_acquire (void)
 
void nros_platform_critical_section_release (uint32_t token)
 
size_t nros_platform_heap_total_bytes (void)
 
size_t nros_platform_heap_used_bytes (void)
 
void nros_platform_sleep_us (size_t us)
 
uint64_t nros_platform_time_now_ns (void)
 
rcl_ret_t rcl_action_client_fini (struct rcl_action_client_t *client, struct rcl_node_t *node)
 
const char * rcl_action_client_get_action_name (const struct rcl_action_client_t *client)
 
struct rcl_action_client_options_t rcl_action_client_get_default_options (void)
 
rcl_ret_t rcl_action_client_init (struct rcl_action_client_t *client, const struct rcl_node_t *node, const struct rclc_action_type_t *type_info, const char *action_name, const struct rcl_action_client_options_t *options)
 
struct rcl_action_client_t rcl_action_get_zero_initialized_client (void)
 
struct rcl_action_server_t rcl_action_get_zero_initialized_server (void)
 
rcl_ret_t rcl_action_server_fini (struct rcl_action_server_t *server, struct rcl_node_t *node)
 
const char * rcl_action_server_get_action_name (const struct rcl_action_server_t *server)
 
struct rcl_action_server_options_t rcl_action_server_get_default_options (void)
 
rcl_ret_t rcl_client_fini (struct rcl_client_t *client, struct rcl_node_t *node)
 
struct rcl_client_options_t rcl_client_get_default_options (void)
 
const char * rcl_client_get_service_name (const struct rcl_client_t *client)
 
bool rcl_client_is_valid (const struct rcl_client_t *client)
 
rcl_ret_t rcl_clock_fini (struct rcl_clock_t *clock)
 
rcl_ret_t rcl_clock_get_now (const struct rcl_clock_t *clock, int64_t *nanoseconds)
 
rcl_ret_t rcl_clock_init (enum rcl_clock_type_t clock_type, struct rcl_clock_t *clock, struct rcl_allocator_t *allocator)
 
bool rcl_clock_time_started (const struct rcl_clock_t *clock)
 
rcl_ret_t rcl_disable_ros_time_override (const struct rcl_clock_t *clock)
 
rcl_ret_t rcl_enable_ros_time_override (const struct rcl_clock_t *clock)
 
struct rcl_allocator_t rcl_get_default_allocator (void)
 
struct rcl_client_t rcl_get_zero_initialized_client (void)
 
struct rcl_guard_condition_t rcl_get_zero_initialized_guard_condition (void)
 
struct rcl_node_t rcl_get_zero_initialized_node (void)
 
struct rcl_publisher_t rcl_get_zero_initialized_publisher (void)
 
struct rcl_service_t rcl_get_zero_initialized_service (void)
 
struct rcl_subscription_t rcl_get_zero_initialized_subscription (void)
 
struct rcl_timer_t rcl_get_zero_initialized_timer (void)
 
rcl_ret_t rcl_guard_condition_fini (struct rcl_guard_condition_t *guard)
 
rcl_ret_t rcl_is_enabled_ros_time_override (const struct rcl_clock_t *clock, bool *is_enabled)
 
rcl_ret_t rcl_node_fini (struct rcl_node_t *node)
 
struct rcl_node_options_t rcl_node_get_default_options (void)
 
rcl_ret_t rcl_node_get_domain_id (const struct rcl_node_t *node, size_t *domain_id)
 
const char * rcl_node_get_name (const struct rcl_node_t *node)
 
const char * rcl_node_get_namespace (const struct rcl_node_t *node)
 
bool rcl_node_is_valid (const struct rcl_node_t *node)
 
rcl_ret_t rcl_publish (const struct rcl_publisher_t *publisher, const void *ros_message, struct rmw_publisher_allocation_t *allocation)
 
rcl_ret_t rcl_publisher_assert_liveliness (const struct rcl_publisher_t *publisher)
 
rcl_ret_t rcl_publisher_fini (struct rcl_publisher_t *publisher, struct rcl_node_t *node)
 
struct rcl_publisher_options_t rcl_publisher_get_default_options (void)
 
const char * rcl_publisher_get_topic_name (const struct rcl_publisher_t *publisher)
 
bool rcl_publisher_is_valid (const struct rcl_publisher_t *publisher)
 
rcl_ret_t rcl_service_fini (struct rcl_service_t *service, struct rcl_node_t *node)
 
struct rcl_service_options_t rcl_service_get_default_options (void)
 
const char * rcl_service_get_service_name (const struct rcl_service_t *service)
 
bool rcl_service_is_valid (const struct rcl_service_t *service)
 
rcl_ret_t rcl_set_ros_time_override (const struct rcl_clock_t *clock, int64_t nanoseconds)
 
rcl_ret_t rcl_subscription_fini (struct rcl_subscription_t *subscription, struct rcl_node_t *node)
 
struct rcl_subscription_options_t rcl_subscription_get_default_options (void)
 
const char * rcl_subscription_get_topic_name (const struct rcl_subscription_t *subscription)
 
bool rcl_subscription_is_valid (const struct rcl_subscription_t *subscription)
 
rcl_ret_t rcl_timer_cancel (struct rcl_timer_t *timer)
 
rcl_ret_t rcl_timer_exchange_period (const struct rcl_timer_t *timer, int64_t new_period, int64_t *old_period)
 
rcl_ret_t rcl_timer_fini (struct rcl_timer_t *timer)
 
rcl_ret_t rcl_timer_get_next_call_time (const struct rcl_timer_t *timer, int64_t *next_call_time)
 
rcl_ret_t rcl_timer_get_time_since_last_call (const struct rcl_timer_t *timer, int64_t *time_since_last_call_ns)
 
rcl_ret_t rcl_timer_get_time_until_next_call (const struct rcl_timer_t *timer, int64_t *time_until_next_call_ns)
 
rcl_ret_t rcl_timer_is_canceled (const struct rcl_timer_t *timer, bool *is_canceled)
 
rcl_ret_t rcl_timer_is_ready (const struct rcl_timer_t *timer, bool *is_ready)
 
rcl_ret_t rcl_timer_reset (struct rcl_timer_t *timer)
 
rcl_ret_t rcl_trigger_guard_condition (struct rcl_guard_condition_t *guard)
 
rcl_ret_t rclc_action_abort (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *result, size_t result_len)
 
rcl_ret_t rclc_action_cancel_goal (struct rcl_action_client_t *client, const struct rclc_goal_uuid_t *goal_uuid)
 
rcl_ret_t rclc_action_canceled (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *result, size_t result_len)
 
bool rclc_action_client_action_server_is_ready (const struct rcl_action_client_t *client, struct rclc_executor_t *executor)
 
rcl_ret_t rclc_action_client_poll (struct rcl_action_client_t *client)
 
rcl_ret_t rclc_action_client_set_feedback_callback (struct rcl_action_client_t *client, rclc_feedback_callback_t callback, void *context)
 
rcl_ret_t rclc_action_client_set_goal_response_callback (struct rcl_action_client_t *client, rclc_goal_response_callback_t callback, void *context)
 
rcl_ret_t rclc_action_client_set_result_callback (struct rcl_action_client_t *client, rclc_result_callback_t callback, void *context)
 
rcl_ret_t rclc_action_client_wait_for_action_server (struct rcl_action_client_t *client, struct rclc_executor_t *executor, uint32_t timeout_ms)
 
rcl_ret_t rclc_action_execute (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal)
 
rcl_ret_t rclc_action_expire_goals (struct rcl_action_server_t *server, size_t *num_expired)
 
rcl_ret_t rclc_action_get_goal_status (const struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, enum rclc_goal_status_t *status)
 
rcl_ret_t rclc_action_get_result (struct rcl_action_client_t *client, struct rclc_executor_t *executor, const struct rclc_goal_uuid_t *goal_uuid, enum rclc_goal_status_t *status, uint8_t *result, size_t result_capacity, size_t *result_len)
 
rcl_ret_t rclc_action_get_result_async (struct rcl_action_client_t *client, const struct rclc_goal_uuid_t *goal_uuid)
 
rcl_ret_t rclc_action_publish_feedback_raw (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *feedback, size_t feedback_len)
 
rcl_ret_t rclc_action_send_goal (struct rcl_action_client_t *client, struct rclc_executor_t *executor, const uint8_t *goal, size_t goal_len, struct rclc_goal_uuid_t *goal_uuid)
 
rcl_ret_t rclc_action_send_goal_async (struct rcl_action_client_t *client, const uint8_t *goal, size_t goal_len, struct rclc_goal_uuid_t *goal_uuid)
 
rcl_ret_t rclc_action_server_get_active_goal_count (struct rcl_action_server_t *server, size_t *out)
 
bool rclc_action_server_goal_exists (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal)
 
rcl_ret_t rclc_action_server_init_with_callbacks (struct rcl_action_server_t *server, const struct rcl_node_t *node, const char *action_name, const struct rclc_action_type_t *type_info, rclc_goal_callback_t goal_callback, rclc_cancel_callback_t cancel_callback, rclc_accepted_callback_t accepted_callback, void *context)
 
rcl_ret_t rclc_action_server_init_with_options (struct rcl_action_server_t *server, const struct rcl_node_t *node, const char *action_name, const struct rclc_action_type_t *type_info, rclc_goal_callback_t goal_callback, rclc_cancel_callback_t cancel_callback, rclc_accepted_callback_t accepted_callback, void *context, const struct rclc_qos_t *qos, const struct rcl_action_server_options_t *options)
 
rcl_ret_t rclc_action_server_init_with_qos (struct rcl_action_server_t *server, const struct rcl_node_t *node, const char *action_name, const struct rclc_action_type_t *type_info, rclc_goal_callback_t goal_callback, rclc_cancel_callback_t cancel_callback, rclc_accepted_callback_t accepted_callback, void *context, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_action_succeed (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *result, size_t result_len)
 
rcl_ret_t rclc_action_try_recv_feedback (struct rcl_action_client_t *client)
 
int32_t rclc_cdr_align (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, size_t alignment)
 
int64_t rclc_cdr_begin_dheader (uint8_t **ptr, const uint8_t *end, const uint8_t *origin)
 
int64_t rclc_cdr_begin_dheader_read (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin)
 
int32_t rclc_cdr_end_dheader (int64_t mark, uint8_t **ptr, const uint8_t *end, const uint8_t *origin)
 
int32_t rclc_cdr_end_dheader_read (int64_t scope, const uint8_t **ptr, const uint8_t *end, const uint8_t *origin)
 
int32_t rclc_cdr_read_bool (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, bool *value)
 
int32_t rclc_cdr_read_f32 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, float *value)
 
int32_t rclc_cdr_read_f64 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, double *value)
 
int32_t rclc_cdr_read_i16 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int16_t *value)
 
int32_t rclc_cdr_read_i32 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int32_t *value)
 
int32_t rclc_cdr_read_i64 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int64_t *value)
 
int32_t rclc_cdr_read_i8 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int8_t *value)
 
int32_t rclc_cdr_read_string (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, char *value, size_t max_len)
 
int32_t rclc_cdr_read_u16 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint16_t *value)
 
int32_t rclc_cdr_read_u32 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint32_t *value)
 
int32_t rclc_cdr_read_u64 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint64_t *value)
 
int32_t rclc_cdr_read_u8 (const uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint8_t *value)
 
int32_t rclc_cdr_write_bool (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, bool value)
 
int32_t rclc_cdr_write_encaps_header (uint8_t **ptr, const uint8_t *end)
 
int32_t rclc_cdr_write_f32 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, float value)
 
int32_t rclc_cdr_write_f64 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, double value)
 
int32_t rclc_cdr_write_i16 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int16_t value)
 
int32_t rclc_cdr_write_i32 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int32_t value)
 
int32_t rclc_cdr_write_i64 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int64_t value)
 
int32_t rclc_cdr_write_i8 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, int8_t value)
 
int32_t rclc_cdr_write_string (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, const char *value)
 
int32_t rclc_cdr_write_string_n (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, const char *data, size_t data_len)
 
int32_t rclc_cdr_write_u16 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint16_t value)
 
int32_t rclc_cdr_write_u32 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint32_t value)
 
int32_t rclc_cdr_write_u64 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint64_t value)
 
int32_t rclc_cdr_write_u8 (uint8_t **ptr, const uint8_t *end, const uint8_t *origin, uint8_t value)
 
rcl_ret_t rclc_clear_custom_transport (void)
 
rcl_ret_t rclc_client_call (struct rcl_client_t *client, const uint8_t *request_data, size_t request_len, uint8_t *response_data, size_t response_capacity, size_t *response_len)
 
rcl_ret_t rclc_client_init_default (struct rcl_client_t *client, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name)
 
rcl_ret_t rclc_client_init_with_options (struct rcl_client_t *client, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name, const struct rclc_qos_t *qos, const struct rcl_client_options_t *options)
 
rcl_ret_t rclc_client_init_with_qos (struct rcl_client_t *client, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_client_request_publisher_get_actual_qos (const struct rcl_client_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_client_response_subscription_get_actual_qos (const struct rcl_client_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_client_send_request_async (struct rcl_client_t *client, const uint8_t *request_data, size_t request_len)
 
rcl_ret_t rclc_client_server_available (struct rcl_client_t *client, int32_t *out)
 
bool rclc_client_service_is_ready (const struct rcl_client_t *client)
 
rcl_ret_t rclc_client_set_response_callback (struct rcl_client_t *client, rclc_response_callback_t callback, void *context)
 
rcl_ret_t rclc_client_set_timeout (struct rcl_client_t *client, uint32_t timeout_ms)
 
rcl_ret_t rclc_client_take_response (struct rcl_client_t *client, uint8_t *response_data, size_t response_capacity, size_t *response_len)
 
rcl_ret_t rclc_client_wait_for_service (struct rcl_client_t *client, uint32_t timeout_ms)
 
rcl_ret_t rclc_clock_get_now_time (const struct rcl_clock_t *clock, struct rclc_time_t *time_out)
 
enum rcl_clock_type_t rclc_clock_get_type (const struct rcl_clock_t *clock)
 
struct rcl_clock_t rclc_clock_get_zero_initialized (void)
 
bool rclc_clock_is_valid (const struct rcl_clock_t *clock)
 
struct rcl_duration_t rclc_duration_from_nanoseconds (int64_t nanoseconds)
 
rcl_ret_t rclc_executor_add_on_shutdown_callback (struct rclc_executor_t *executor, rclc_shutdown_callback_t callback, void *context, rclc_shutdown_callback_handle_t *out_handle)
 
rcl_ret_t rclc_executor_add_pre_shutdown_callback (struct rclc_executor_t *executor, rclc_shutdown_callback_t callback, void *context, rclc_shutdown_callback_handle_t *out_handle)
 
rcl_ret_t rclc_executor_add_service_raw (struct rclc_executor_t *executor, struct rcl_service_t *service, rclc_service_raw_callback_t callback, void *context)
 
rcl_ret_t rclc_executor_add_subscription_in_group (struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, rclc_subscription_raw_callback_t callback, void *context, enum rclc_executor_handle_invocation_t invocation, const char *callback_group)
 
rcl_ret_t rclc_executor_add_subscription_raw (struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, rclc_subscription_raw_callback_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)
 
rcl_ret_t rclc_executor_add_subscription_raw_validated (struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, rclc_subscription_validated_callback_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)
 
rcl_ret_t rclc_executor_add_subscription_raw_with_info (struct rclc_executor_t *executor, const struct rcl_node_t *node, const char *topic_name, const char *type_name, const char *type_hash, const struct rclc_qos_t *qos, rclc_subscription_info_callback_t callback, void *context)
 
rcl_ret_t rclc_executor_add_subscription_with_context (struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, void *msg, rclc_subscription_callback_with_context_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)
 
rcl_ret_t rclc_executor_add_subscription_with_info (struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, rclc_subscription_info_callback_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)
 
rcl_ret_t rclc_executor_add_time_triggered_dispatcher (struct rclc_executor_t *executor, uint32_t major_frame_us)
 
rcl_ret_t rclc_executor_add_timer (struct rclc_executor_t *executor, struct rcl_timer_t *timer)
 
rcl_ret_t rclc_executor_add_timer_in_group (struct rclc_executor_t *executor, struct rcl_timer_t *timer, const char *callback_group)
 
rcl_ret_t rclc_executor_attach_action_client (struct rclc_executor_t *executor, struct rcl_action_client_t *client)
 
rcl_ret_t rclc_executor_attach_action_server (struct rclc_executor_t *executor, struct rcl_action_server_t *server)
 
rcl_ret_t rclc_executor_attach_client (struct rclc_executor_t *executor, struct rcl_client_t *client)
 
rcl_ret_t rclc_executor_bind_handle_to_sched_context (struct rclc_executor_t *executor, size_t handle, rclc_sched_context_id_t sc_id)
 
rcl_ret_t rclc_executor_cancel (struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_count_publishers (struct rclc_executor_t *executor, const char *topic_name, size_t *out_count)
 
rcl_ret_t rclc_executor_count_subscribers (struct rclc_executor_t *executor, const char *topic_name, size_t *out_count)
 
rcl_ret_t rclc_executor_create_sched_context (struct rclc_executor_t *executor, const struct rclc_sched_context_t *cfg, rclc_sched_context_id_t *out_sc_id)
 
rclc_sched_context_id_t rclc_executor_default_sched_context_id (void)
 
rcl_ret_t rclc_executor_fini (struct rclc_executor_t *executor)
 
size_t rclc_executor_get_arena_capacity (const struct rclc_executor_t *executor)
 
size_t rclc_executor_get_arena_used (const struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_get_client_names_and_types_by_node (struct rclc_executor_t *executor, const char *node_name, const char *node_namespace, rclc_names_and_types_visit_fn visit, void *ctx)
 
int rclc_executor_get_handle_count (const struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_get_node_names (struct rclc_executor_t *executor, rclc_node_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_publisher_names_and_types_by_node (struct rclc_executor_t *executor, const char *node_name, const char *node_namespace, rclc_names_and_types_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_publishers_info_by_topic (struct rclc_executor_t *executor, const char *topic_name, rclc_endpoint_info_visit_fn visit, void *ctx)
 
int rclc_executor_get_remaining_handles (const struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_get_service_names_and_types (struct rclc_executor_t *executor, rclc_names_and_types_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_service_names_and_types_by_node (struct rclc_executor_t *executor, const char *node_name, const char *node_namespace, rclc_names_and_types_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_subscriber_names_and_types_by_node (struct rclc_executor_t *executor, const char *node_name, const char *node_namespace, rclc_names_and_types_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_subscriptions_info_by_topic (struct rclc_executor_t *executor, const char *topic_name, rclc_endpoint_info_visit_fn visit, void *ctx)
 
rcl_ret_t rclc_executor_get_topic_names_and_types (struct rclc_executor_t *executor, rclc_names_and_types_visit_fn visit, void *ctx)
 
struct rclc_executor_t rclc_executor_get_zero_initialized_executor (void)
 
rcl_ret_t rclc_executor_init (struct rclc_executor_t *executor, struct rcl_context_t *context, size_t number_of_handles, const struct rcl_allocator_t *allocator)
 
bool rclc_executor_is_spinning (const struct rclc_executor_t *executor)
 
bool rclc_executor_is_valid (const struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_lifecycle_change_state (struct rclc_executor_t *executor, uint8_t transition_id)
 
uint8_t rclc_executor_lifecycle_get_current_state (struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_lifecycle_register_on_activate (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_lifecycle_register_on_cleanup (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_lifecycle_register_on_configure (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_lifecycle_register_on_deactivate (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_lifecycle_register_on_error (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_lifecycle_register_on_shutdown (struct rclc_executor_t *executor, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_executor_node_init (struct rclc_executor_t *executor, struct rcl_node_t *node, const char *name, const struct rcl_node_options_t *options)
 
rcl_ret_t rclc_executor_ping (struct rclc_executor_t *executor, int32_t timeout_ms)
 
rcl_ret_t rclc_executor_register_lifecycle_services (struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_remove_action_client (struct rclc_executor_t *executor, struct rcl_action_client_t *client)
 
rcl_ret_t rclc_executor_remove_action_server (struct rclc_executor_t *executor, struct rcl_action_server_t *server)
 
rcl_ret_t rclc_executor_remove_client (struct rclc_executor_t *executor, const struct rcl_client_t *client)
 
rcl_ret_t rclc_executor_remove_on_shutdown_callback (struct rclc_executor_t *executor, rclc_shutdown_callback_handle_t handle)
 
rcl_ret_t rclc_executor_remove_pre_shutdown_callback (struct rclc_executor_t *executor, rclc_shutdown_callback_handle_t handle)
 
rcl_ret_t rclc_executor_remove_service (struct rclc_executor_t *executor, const struct rcl_service_t *service)
 
rcl_ret_t rclc_executor_remove_subscription (struct rclc_executor_t *executor, const struct rcl_subscription_t *subscription)
 
rcl_ret_t rclc_executor_remove_timer (struct rclc_executor_t *executor, const struct rcl_timer_t *timer)
 
rcl_ret_t rclc_executor_set_semantics (struct rclc_executor_t *executor, enum rclc_executor_semantics_t semantics)
 
rcl_ret_t rclc_executor_set_timeout (struct rclc_executor_t *executor, uint64_t timeout_ns)
 
rcl_ret_t rclc_executor_set_trigger (struct rclc_executor_t *executor, rclc_executor_trigger_t trigger, void *context)
 
rcl_ret_t rclc_executor_spin (struct rclc_executor_t *executor)
 
rcl_ret_t rclc_executor_spin_one_period (struct rclc_executor_t *executor, uint64_t period_ns)
 
rcl_ret_t rclc_executor_spin_period (struct rclc_executor_t *executor, uint64_t period_ns)
 
rcl_ret_t rclc_executor_spin_some (struct rclc_executor_t *executor, uint64_t timeout_ns)
 
bool rclc_executor_trigger_all (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
bool rclc_executor_trigger_always (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
bool rclc_executor_trigger_any (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
bool rclc_executor_trigger_index (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
bool rclc_executor_trigger_one (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)
 
rcl_ret_t rclc_executor_wait_for_publishers (struct rclc_executor_t *executor, const char *topic_name, size_t count, uint32_t timeout_ms)
 
rcl_ret_t rclc_executor_wait_for_subscribers (struct rclc_executor_t *executor, const char *topic_name, size_t count, uint32_t timeout_ms)
 
rcl_ret_t rclc_get_fully_qualified_name (const char *node_name, const char *node_namespace, char *buf, size_t buf_len, size_t *out_len)
 
rcl_ret_t rclc_get_ros_time_override (const struct rcl_clock_t *clock, int64_t *nanoseconds)
 
struct rclc_polling_action_client_t rclc_get_zero_initialized_polling_action_client (void)
 
struct rclc_polling_action_server_t rclc_get_zero_initialized_polling_action_server (void)
 
struct rclc_polling_client_t rclc_get_zero_initialized_polling_client (void)
 
struct rclc_polling_service_t rclc_get_zero_initialized_polling_service (void)
 
struct rclc_polling_subscription_t rclc_get_zero_initialized_polling_subscription (void)
 
const char * rclc_goal_status_to_string (enum rclc_goal_status_t status)
 
bool rclc_goal_uuid_equal (const struct rclc_goal_uuid_t *a, const struct rclc_goal_uuid_t *b)
 
rcl_ret_t rclc_goal_uuid_generate (struct rclc_goal_uuid_t *uuid)
 
rcl_ret_t rclc_guard_condition_clear (struct rcl_guard_condition_t *guard)
 
bool rclc_guard_condition_is_triggered (const struct rcl_guard_condition_t *guard)
 
bool rclc_guard_condition_is_valid (const struct rcl_guard_condition_t *guard)
 
rcl_ret_t rclc_guard_condition_trigger (struct rcl_guard_condition_t *guard)
 
rcl_ret_t rclc_has_custom_transport (void)
 
size_t rclc_heap_peak_bytes (void)
 
size_t rclc_heap_platform_used_bytes (void)
 
size_t rclc_heap_total_bytes (void)
 
size_t rclc_heap_used_bytes (void)
 
rcl_ret_t rclc_lifecycle_fini (struct rcl_lifecycle_state_machine_t *sm)
 
uint8_t rclc_lifecycle_get_current_state (const struct rcl_lifecycle_state_machine_t *sm)
 
struct rcl_lifecycle_state_machine_t rclc_lifecycle_get_zero_initialized (void)
 
rcl_ret_t rclc_lifecycle_init (struct rcl_lifecycle_state_machine_t *sm)
 
rcl_ret_t rclc_lifecycle_register_on_error (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_lifecycle_register_on_shutdown (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
const char * rclc_lifecycle_state_label (uint8_t state_id)
 
rcl_ret_t rclc_lifecycle_state_machine_change_state (struct rcl_lifecycle_state_machine_t *sm, uint8_t transition_id)
 
rcl_ret_t rclc_lifecycle_state_machine_register_on_activate (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_lifecycle_state_machine_register_on_cleanup (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_lifecycle_state_machine_register_on_configure (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
rcl_ret_t rclc_lifecycle_state_machine_register_on_deactivate (struct rcl_lifecycle_state_machine_t *sm, rclc_lifecycle_callback_t cb, void *context)
 
uint8_t rclc_lifecycle_transition_goal_state (uint8_t transition_id)
 
rcl_ret_t rclc_lifecycle_transition_graph (const uint8_t **out_ids, size_t *out_count)
 
const char * rclc_lifecycle_transition_label (uint8_t transition_id)
 
uint8_t rclc_lifecycle_transition_start_state (uint8_t transition_id)
 
void rclc_monitors_arm (void)
 
rcl_ret_t rclc_node_create_guard_condition (struct rcl_node_t *node, struct rcl_guard_condition_t *out, rclc_guard_condition_callback_t callback, void *context)
 
rcl_ret_t rclc_node_get_fully_qualified_name (const struct rcl_node_t *node, char *buf, size_t buf_len, size_t *out_len)
 
rcl_ret_t rclc_node_get_graph_guard_condition (struct rcl_node_t *node, struct rcl_guard_condition_t *out, rclc_guard_condition_callback_t callback, void *context)
 
const void * rclc_node_get_logger (const struct rcl_node_t *node)
 
const char * rclc_node_get_serialization_format (const struct rcl_node_t *node)
 
rcl_ret_t rclc_node_init_default (struct rcl_node_t *node, const char *name, const char *namespace_, const struct rclc_support_t *support)
 
rcl_ret_t rclc_node_init_ex (struct rcl_node_t *node, const struct rclc_support_t *support, const char *name, const struct rcl_node_options_t *options)
 
rcl_ret_t rclc_node_resolve_name (const struct rcl_node_t *node, const char *input_name, bool only_expand, char *output_name, size_t output_size)
 
rcl_ret_t rclc_node_set_qos_overrides (struct rcl_node_t *node, const struct rclc_qos_override_t *overrides, size_t len)
 
rcl_ret_t rclc_polling_action_client_fini (struct rclc_polling_action_client_t *client)
 
rcl_ret_t rclc_polling_action_client_init (struct rclc_polling_action_client_t *client, const struct rcl_node_t *node, const struct rclc_action_type_t *type_info, const char *action_name)
 
rcl_ret_t rclc_polling_action_client_send_cancel_request_raw (struct rclc_polling_action_client_t *client, const uint8_t(*goal_id)[16])
 
rcl_ret_t rclc_polling_action_client_send_get_result_request_raw (struct rclc_polling_action_client_t *client, const uint8_t(*goal_id)[16])
 
rcl_ret_t rclc_polling_action_client_send_goal_raw (struct rclc_polling_action_client_t *client, const uint8_t *goal_cdr, size_t goal_len, uint8_t(*goal_id_out)[16])
 
rcl_ret_t rclc_polling_action_client_set_cancel_response_wake_callback (struct rclc_polling_action_client_t *client, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_action_client_set_feedback_wake_callback (struct rclc_polling_action_client_t *client, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_action_client_set_goal_response_wake_callback (struct rclc_polling_action_client_t *client, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_action_client_set_result_wake_callback (struct rclc_polling_action_client_t *client, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
int32_t rclc_polling_action_client_try_recv_cancel_response_raw (struct rclc_polling_action_client_t *client, uint8_t *buf, size_t buf_len)
 
int32_t rclc_polling_action_client_try_recv_feedback_raw (struct rclc_polling_action_client_t *client, uint8_t *buf, size_t buf_len, uint8_t(*goal_id_out)[16])
 
int32_t rclc_polling_action_client_try_recv_goal_response_raw (struct rclc_polling_action_client_t *client, uint8_t *buf, size_t buf_len)
 
int32_t rclc_polling_action_client_try_recv_result_raw (struct rclc_polling_action_client_t *client, uint8_t *buf, size_t buf_len)
 
rcl_ret_t rclc_polling_action_server_accept_goal_raw (struct rclc_polling_action_server_t *server, const uint8_t(*goal_id)[16], int64_t sequence_number)
 
rcl_ret_t rclc_polling_action_server_complete_goal_raw (struct rclc_polling_action_server_t *server, const uint8_t(*goal_id)[16], enum rclc_goal_status_t status, const uint8_t *result_cdr, size_t result_len)
 
rcl_ret_t rclc_polling_action_server_expire_goals (struct rclc_polling_action_server_t *server, size_t *num_expired)
 
rcl_ret_t rclc_polling_action_server_fini (struct rclc_polling_action_server_t *server)
 
rcl_ret_t rclc_polling_action_server_get_active_goal_count (struct rclc_polling_action_server_t *server, size_t *out)
 
bool rclc_polling_action_server_goal_exists (struct rclc_polling_action_server_t *server, const struct rclc_goal_handle_t *goal)
 
rcl_ret_t rclc_polling_action_server_init (struct rclc_polling_action_server_t *server, const struct rcl_node_t *node, const struct rclc_action_type_t *type_info, const char *action_name)
 
rcl_ret_t rclc_polling_action_server_publish_feedback_raw (struct rclc_polling_action_server_t *server, const uint8_t(*goal_id)[16], const uint8_t *feedback_cdr, size_t feedback_len)
 
rcl_ret_t rclc_polling_action_server_reject_goal_raw (struct rclc_polling_action_server_t *server, int64_t sequence_number)
 
rcl_ret_t rclc_polling_action_server_send_cancel_reply_raw (struct rclc_polling_action_server_t *server, int64_t sequence_number, enum rclc_cancel_return_code_t return_code, const uint8_t(*accepted)[16], size_t accepted_count)
 
rcl_ret_t rclc_polling_action_server_set_cancel_wake_callback (struct rclc_polling_action_server_t *server, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_action_server_set_get_result_wake_callback (struct rclc_polling_action_server_t *server, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_action_server_set_goal_wake_callback (struct rclc_polling_action_server_t *server, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
int32_t rclc_polling_action_server_try_handle_get_result_raw (struct rclc_polling_action_server_t *server, const uint8_t *default_result_cdr, size_t default_result_len)
 
int32_t rclc_polling_action_server_try_recv_cancel_request_raw (struct rclc_polling_action_server_t *server, uint8_t(*goal_id_out)[16], int64_t *sequence_number_out, enum rclc_goal_status_t *current_status_out)
 
int32_t rclc_polling_action_server_try_recv_goal_request_raw (struct rclc_polling_action_server_t *server, uint8_t *buf, size_t buf_len, uint8_t(*goal_id_out)[16], int64_t *sequence_number_out)
 
rcl_ret_t rclc_polling_client_fini (struct rclc_polling_client_t *client)
 
rcl_ret_t rclc_polling_client_init (struct rclc_polling_client_t *client, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name)
 
rcl_ret_t rclc_polling_client_request_publisher_get_actual_qos (struct rclc_polling_client_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_polling_client_response_subscription_get_actual_qos (struct rclc_polling_client_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_polling_client_send_request_raw (struct rclc_polling_client_t *client, const uint8_t *data, size_t len)
 
rcl_ret_t rclc_polling_client_set_wake_callback (struct rclc_polling_client_t *client, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
int32_t rclc_polling_client_take_response_raw (struct rclc_polling_client_t *client, uint8_t *buf, size_t buf_len)
 
rcl_ret_t rclc_polling_service_fini (struct rclc_polling_service_t *service)
 
rcl_ret_t rclc_polling_service_init (struct rclc_polling_service_t *service, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name)
 
rcl_ret_t rclc_polling_service_request_subscription_get_actual_qos (struct rclc_polling_service_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_polling_service_response_publisher_get_actual_qos (struct rclc_polling_service_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_polling_service_send_response_raw (struct rclc_polling_service_t *service, int64_t sequence_number, const uint8_t *data, size_t len)
 
rcl_ret_t rclc_polling_service_set_wake_callback (struct rclc_polling_service_t *service, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
int32_t rclc_polling_service_take_request_raw (struct rclc_polling_service_t *service, uint8_t *buf, size_t buf_len, int64_t *sequence_number)
 
int32_t rclc_polling_subscription_borrow (struct rclc_polling_subscription_t *subscription, const uint8_t **out_buf, size_t *out_len, void **out_token)
 
rcl_ret_t rclc_polling_subscription_fini (struct rclc_polling_subscription_t *subscription)
 
rcl_ret_t rclc_polling_subscription_get_actual_qos (struct rclc_polling_subscription_t *subscription, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_polling_subscription_init (struct rclc_polling_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name)
 
rcl_ret_t rclc_polling_subscription_init_with_qos (struct rclc_polling_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_polling_subscription_release (struct rclc_polling_subscription_t *subscription, void *token)
 
rcl_ret_t rclc_polling_subscription_set_wake_callback (struct rclc_polling_subscription_t *subscription, struct rclc_wake_state_t *state, void(*cb)(void *), void *ctx)
 
rcl_ret_t rclc_polling_subscription_take (struct rclc_polling_subscription_t *subscription, void *ros_message, struct rmw_subscription_allocation_t *allocation)
 
int32_t rclc_polling_subscription_take_sequence (struct rclc_polling_subscription_t *subscription, uint8_t *buf, size_t per_msg_cap, size_t max_msgs, size_t *out_lens)
 
int32_t rclc_polling_subscription_take_serialized (struct rclc_polling_subscription_t *subscription, uint8_t *buf, size_t buf_len)
 
int32_t rclc_polling_subscription_take_validated (struct rclc_polling_subscription_t *subscription, uint8_t *buf, size_t buf_len, struct rclc_integrity_status_t *out_status)
 
rcl_ret_t rclc_publish_raw (const struct rcl_publisher_t *publisher, const uint8_t *data, size_t len)
 
rcl_ret_t rclc_publisher_commit (const struct rcl_publisher_t *publisher, void *token, size_t actual_len)
 
rcl_ret_t rclc_publisher_discard (const struct rcl_publisher_t *publisher, void *token)
 
rcl_ret_t rclc_publisher_get_actual_qos (const struct rcl_publisher_t *publisher, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_publisher_get_gid (const struct rcl_publisher_t *publisher, uint8_t *out_gid, size_t gid_capacity)
 
rcl_ret_t rclc_publisher_get_subscription_count (const struct rcl_publisher_t *publisher, struct rclc_executor_t *executor, size_t *out_count)
 
rcl_ret_t rclc_publisher_init_default (struct rcl_publisher_t *publisher, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name)
 
rcl_ret_t rclc_publisher_init_with_options (struct rcl_publisher_t *publisher, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name, const struct rclc_qos_t *qos, const struct rcl_publisher_options_t *options)
 
rcl_ret_t rclc_publisher_init_with_qos (struct rcl_publisher_t *publisher, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_publisher_loan (const struct rcl_publisher_t *publisher, size_t requested_len, uint8_t **out_buf, size_t *out_cap, void **out_token)
 
rcl_ret_t rclc_publisher_publish_streamed (const struct rcl_publisher_t *publisher, void(*size_cb)(size_t *out_total_len, void *user_ctx), void(*chunk_cb)(uint8_t *out_buf, size_t cap, size_t *out_written, void *user_ctx), void *user_ctx)
 
rcl_ret_t rclc_publisher_set_liveliness_lost_callback (struct rcl_publisher_t *_pub_, rclc_event_publisher_count_cb_t _cb, void *_user_context)
 
rcl_ret_t rclc_publisher_set_offered_deadline_missed_callback (struct rcl_publisher_t *_pub_, uint32_t _deadline_ms, rclc_event_publisher_count_cb_t _cb, void *_user_context)
 
const char * rclc_qos_policy_kind_to_cstr (uint32_t policy)
 
rcl_ret_t rclc_service_init_default (struct rcl_service_t *service, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name)
 
rcl_ret_t rclc_service_init_with_options (struct rcl_service_t *service, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name, const struct rclc_qos_t *qos, const struct rcl_service_options_t *options)
 
rcl_ret_t rclc_service_init_with_qos (struct rcl_service_t *service, const struct rcl_node_t *node, const struct rclc_service_type_t *type_info, const char *service_name, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_service_request_subscription_get_actual_qos (const struct rcl_service_t *handle, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_service_response_publisher_get_actual_qos (const struct rcl_service_t *handle, struct rclc_qos_t *out_qos)
 
void rclc_service_typed_report_error (int32_t error, const char *type_name)
 
rcl_ret_t rclc_set_custom_transport (const struct nros_transport_ops_t *ops)
 
int32_t rclc_set_default_trace_sink (void(*sink)(uint32_t, uint32_t))
 
void rclc_set_trace_sink (void(*sink)(uint32_t, uint32_t))
 
rcl_ret_t rclc_subscription_get_actual_qos (const struct rcl_subscription_t *subscription, struct rclc_qos_t *out_qos)
 
rcl_ret_t rclc_subscription_get_publisher_count (const struct rcl_subscription_t *subscription, struct rclc_executor_t *executor, size_t *out_count)
 
rcl_ret_t rclc_subscription_init_default (struct rcl_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name)
 
rcl_ret_t rclc_subscription_init_with_options (struct rcl_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name, const struct rclc_qos_t *qos, const struct rcl_subscription_options_t *options)
 
rcl_ret_t rclc_subscription_init_with_qos (struct rcl_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name, const struct rclc_qos_t *qos)
 
rcl_ret_t rclc_subscription_set_liveliness_changed_callback (struct rcl_subscription_t *_sub, rclc_event_liveliness_changed_cb_t _cb, void *_user_context)
 
rcl_ret_t rclc_subscription_set_message_lost_callback (struct rcl_subscription_t *_sub, rclc_event_subscriber_count_cb_t _cb, void *_user_context)
 
rcl_ret_t rclc_subscription_set_requested_deadline_missed_callback (struct rcl_subscription_t *_sub, uint32_t _deadline_ms, rclc_event_subscriber_count_cb_t _cb, void *_user_context)
 
rcl_ret_t rclc_support_fini (struct rclc_support_t *support)
 
struct rclc_support_t rclc_support_get_zero_initialized (void)
 
rcl_ret_t rclc_support_init (struct rclc_support_t *support, int argc, const char *const *argv, const struct rcl_allocator_t *allocator)
 
rcl_ret_t rclc_support_init_named (struct rclc_support_t *support, const char *locator, uint8_t domain_id, const char *session_name)
 
rcl_ret_t rclc_support_init_rmw (struct rclc_support_t *support, const char *locator, uint8_t domain_id, const char *session_name, const char *rmw)
 
rcl_ret_t rclc_support_init_with_locator (struct rclc_support_t *support, const char *locator, uint8_t domain_id)
 
bool rclc_support_is_valid (const struct rclc_support_t *support)
 
struct rclc_time_t rclc_time_add (struct rclc_time_t time, struct rcl_duration_t duration)
 
int rclc_time_compare (struct rclc_time_t a, struct rclc_time_t b)
 
struct rclc_time_t rclc_time_from_nanoseconds (int64_t nanoseconds)
 
struct rclc_time_t rclc_time_sub (struct rclc_time_t time, struct rcl_duration_t duration)
 
int64_t rclc_time_to_nanoseconds (const struct rclc_time_t *time)
 
uint64_t rclc_timer_get_period (const struct rcl_timer_t *timer)
 
rcl_ret_t rclc_timer_init_on_clock (struct rcl_timer_t *timer, const struct rcl_clock_t *clock, uint64_t period_ns, rclc_timer_callback_with_context_t callback, void *context)
 
rcl_ret_t rclc_timer_init_with_context (struct rcl_timer_t *timer, uint64_t period_ns, rclc_timer_callback_with_context_t callback, void *context)
 
bool rclc_timer_is_valid (const struct rcl_timer_t *timer)
 
void rclc_trace_set_take (uint8_t handle, bool on, int32_t stamp_offset)
 
void rclc_trace_set_timer_every (uint8_t handle, uint16_t every)
 
struct rclc_wake_state_t rclc_wake_state_get_zero_initialized (void)
 

Variables

const uint32_t NROS_TRANSPORT_OPS_ABI_VERSION_V1
 
const struct rclc_qos_t RCLC_QOS_DEFAULT
 
const struct rclc_qos_t RCLC_QOS_SENSOR_DATA
 
const struct rclc_qos_t RCLC_QOS_SERVICES
 

Macro Definition Documentation

◆ MAX_RMW_NAME_LEN

#define MAX_RMW_NAME_LEN   32

Maximum length of an RMW backend name (e.g., "zenoh", "cyclonedds", "xrce").

Matches BACKEND_NAME_MAX in nros-rmw-cffi/src/lib.rs. Lifted to a public constant here so rcl_node_options_t can declare a fixed-size buffer that round-trips through the registry without truncation.

◆ NROS_DOMAIN_ID_EXPLICIT_ZERO

#define NROS_DOMAIN_ID_EXPLICIT_ZERO   255

Issue #227 — pass this as domain_id to rclc_support_init[_named] to request an EXPLICIT domain 0. Plain 0 is the UNSET sentinel (defers to ROS_DOMAIN_ID env on hosted, then the baked/default rungs — the #206 model-A ladder). Valid domains cap at 232, so 255 is unambiguous. Hosted env still overrides it, like every explicit argument under model A.

◆ NROS_DOMAIN_ID_INHERIT

#define NROS_DOMAIN_ID_INHERIT   UINT32_MAX

Sentinel value for domain_id_override. When set, the support context's domain_id is used instead of the per-Node override.

◆ NROS_GENERATED_H

#define NROS_GENERATED_H

◆ NROS_MAX_ACTION_NAME_LEN

#define NROS_MAX_ACTION_NAME_LEN   256

Maximum length of an action name

◆ NROS_MAX_CONCURRENT_GOALS

#define NROS_MAX_CONCURRENT_GOALS   4

Maximum number of concurrent goals per action server.

This is a fixed constant (not configurable via env var) because it affects rcl_action_server_t struct layout. Changing it requires rebuilding the runtime and the consuming application together.

◆ NROS_MAX_LOCATOR_LEN

#define NROS_MAX_LOCATOR_LEN   128

Maximum length of a zenoh locator string (e.g., "tcp/127.0.0.1:7447")

◆ NROS_MAX_NAME_LEN

#define NROS_MAX_NAME_LEN   64

Maximum length of a node name

◆ NROS_MAX_NAMESPACE_LEN

#define NROS_MAX_NAMESPACE_LEN   128

Maximum length of a node namespace

◆ NROS_MAX_SERVICE_NAME_LEN

#define NROS_MAX_SERVICE_NAME_LEN   256

Maximum length of a service name

◆ NROS_MAX_TOPIC_LEN

#define NROS_MAX_TOPIC_LEN   256

Maximum length of a topic name

◆ NROS_MAX_TYPE_HASH_LEN

#define NROS_MAX_TYPE_HASH_LEN   128

Maximum length of a type hash (RIHS format)

◆ NROS_MAX_TYPE_NAME_LEN

#define NROS_MAX_TYPE_NAME_LEN   256

Maximum length of a type name (e.g., "std_msgs::msg::dds_::Int32_")

◆ NROS_PUBLISHER_GID_SIZE

#define NROS_PUBLISHER_GID_SIZE   24

The number of bytes in a publisher GID — upstream's RMW_GID_STORAGE_SIZE, and the size of the buffer [rclc_publisher_get_gid] fills.

◆ NROS_SERIALIZATION_FORMAT_ID

#define NROS_SERIALIZATION_FORMAT_ID   1

Image-local discriminant of the linked backend's serialization format (nros_serdes::format::SerializationFormatId). RFC-0088 D2 — image-local: never persist it, never compare it across images.

◆ RCL_RET_ERROR

#define RCL_RET_ERROR   -1

Generic error

◆ RCL_RET_INVALID_ARGUMENT

#define RCL_RET_INVALID_ARGUMENT   -3

Invalid argument passed

◆ RCL_RET_NOT_INIT

#define RCL_RET_NOT_INIT   -7

Not initialized

◆ RCL_RET_OK

#define RCL_RET_OK   0

Success

◆ RCL_RET_TIMEOUT

#define RCL_RET_TIMEOUT   -2

Timeout occurred

◆ RCL_RET_UNSUPPORTED

#define RCL_RET_UNSUPPORTED   -16

The active backend does not implement this operation. Phase 108 status-event setters return this until backend wiring lands per phase (109+).

◆ RCLC_LIFECYCLE_RET_ERROR

#define RCLC_LIFECYCLE_RET_ERROR   2

Transition result: Error

◆ RCLC_LIFECYCLE_RET_FAILURE

#define RCLC_LIFECYCLE_RET_FAILURE   1

Transition result: Failure

◆ RCLC_LIFECYCLE_RET_OK

#define RCLC_LIFECYCLE_RET_OK   0

Transition result: Success

◆ RCLC_LIFECYCLE_STATE_ACTIVE

#define RCLC_LIFECYCLE_STATE_ACTIVE   3

Lifecycle state: Active

◆ RCLC_LIFECYCLE_STATE_ERROR_PROCESSING

#define RCLC_LIFECYCLE_STATE_ERROR_PROCESSING   5

Lifecycle state: ErrorProcessing

◆ RCLC_LIFECYCLE_STATE_FINALIZED

#define RCLC_LIFECYCLE_STATE_FINALIZED   4

Lifecycle state: Finalized

◆ RCLC_LIFECYCLE_STATE_INACTIVE

#define RCLC_LIFECYCLE_STATE_INACTIVE   2

Lifecycle state: Inactive

◆ RCLC_LIFECYCLE_STATE_UNCONFIGURED

#define RCLC_LIFECYCLE_STATE_UNCONFIGURED   1

Lifecycle state: Unconfigured

◆ RCLC_LIFECYCLE_TRANSITION_ACTIVATE

#define RCLC_LIFECYCLE_TRANSITION_ACTIVATE   3

Lifecycle transition: Activate (lifecycle_msgs TRANSITION_ACTIVATE)

◆ RCLC_LIFECYCLE_TRANSITION_CLEANUP

#define RCLC_LIFECYCLE_TRANSITION_CLEANUP   2

Lifecycle transition: Cleanup (lifecycle_msgs TRANSITION_CLEANUP)

◆ RCLC_LIFECYCLE_TRANSITION_CONFIGURE

#define RCLC_LIFECYCLE_TRANSITION_CONFIGURE   1

Lifecycle transition: Configure (lifecycle_msgs TRANSITION_CONFIGURE)

◆ RCLC_LIFECYCLE_TRANSITION_DEACTIVATE

#define RCLC_LIFECYCLE_TRANSITION_DEACTIVATE   4

Lifecycle transition: Deactivate (lifecycle_msgs TRANSITION_DEACTIVATE)

◆ RCLC_LIFECYCLE_TRANSITION_ERROR_RECOVERY

#define RCLC_LIFECYCLE_TRANSITION_ERROR_RECOVERY   60

Lifecycle transition: Error Recovery (lifecycle_msgs TRANSITION_ON_ERROR_SUCCESS). Upstream 8 is TRANSITION_DESTROY, which nano-ros does not implement, and upstream models error recovery as an implicit transition — 60 is upstream's id for its success edge and is what nano-ros already put on the wire for it.

◆ RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_ACTIVE

#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_ACTIVE   7

Lifecycle transition: Shutdown (from Active) (lifecycle_msgs TRANSITION_ACTIVE_SHUTDOWN)

◆ RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_INACTIVE

#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_INACTIVE   6

Lifecycle transition: Shutdown (from Inactive) (lifecycle_msgs TRANSITION_INACTIVE_SHUTDOWN)

◆ RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_UNCONFIGURED

#define RCLC_LIFECYCLE_TRANSITION_SHUTDOWN_UNCONFIGURED   5

Lifecycle transition: Shutdown (from Unconfigured) (lifecycle_msgs TRANSITION_UNCONFIGURED_SHUTDOWN)

◆ RCLC_RET_ALREADY_EXISTS

#define RCLC_RET_ALREADY_EXISTS   -5

Resource already exists

◆ RCLC_RET_BAD_SEQUENCE

#define RCLC_RET_BAD_SEQUENCE   -8

Bad sequence (e.g., wrong order of operations)

◆ RCLC_RET_FULL

#define RCLC_RET_FULL   -6

Resource limit reached (e.g., max handles)

◆ RCLC_RET_NOT_ALLOWED

#define RCLC_RET_NOT_ALLOWED   -12

Operation not allowed (e.g., goal not in correct state)

◆ RCLC_RET_NOT_FOUND

#define RCLC_RET_NOT_FOUND   -4

Resource not found

◆ RCLC_RET_PUBLISH_FAILED

#define RCLC_RET_PUBLISH_FAILED   -10

Publish failed

◆ RCLC_RET_REENTRANT

#define RCLC_RET_REENTRANT   -15

Reentrant call detected — a blocking helper (rclc_client_call, rclc_action_send_goal, rclc_action_get_result) was called from inside a dispatch callback. These functions internally call rclc_executor_spin_some, which is not reentrant.

◆ RCLC_RET_REJECTED

#define RCLC_RET_REJECTED   -13

Request was rejected (e.g., goal rejected by server)

◆ RCLC_RET_SERVICE_FAILED

#define RCLC_RET_SERVICE_FAILED   -9

Service call failed

◆ RCLC_RET_STALE_NODE

#define RCLC_RET_STALE_NODE   -17

phase-379 W4 — the entity's node reference no longer names a live binding.

Returned when an entity is used or finalised after rcl_node_fini retired the slot it was created on. Before W4 the entity held a raw *const rcl_node_t that nothing dereferenced, so this case SUCCEEDED silently; the identity makes it detectable. Distinct from RCL_RET_NOT_INIT (never initialised) and RCLC_RET_BAD_SEQUENCE (initialised, wrong order) because the remedy differs: the node outlived by this entity has to be finalised LAST.

◆ RCLC_RET_SUBSCRIPTION_FAILED

#define RCLC_RET_SUBSCRIPTION_FAILED   -11

Subscription failed

◆ RCLC_RET_TRY_AGAIN

#define RCLC_RET_TRY_AGAIN   -14

Operation not yet ready (e.g., async response still pending). Caller should spin the executor and try again.

◆ RCLC_SERVICE_TYPED_ERR_NO_CALLBACK

#define RCLC_SERVICE_TYPED_ERR_NO_CALLBACK   -5

The handler struct reached the trampoline with no user callback installed — <Srv>_service_handler_init was skipped or the struct was re-zeroed.

◆ RCLC_SERVICE_TYPED_ERR_REQUEST_DESERIALIZE

#define RCLC_SERVICE_TYPED_ERR_REQUEST_DESERIALIZE   -1

<Req>_deserialize rejected the request bytes — the request was malformed, truncated, or encoded by a peer whose schema disagrees. No reply is sent.

◆ RCLC_SERVICE_TYPED_ERR_REQUEST_SERIALIZE

#define RCLC_SERVICE_TYPED_ERR_REQUEST_SERIALIZE   -3

<Req>_serialize did not fit the scratch buffer the caller supplied to <Srv>_client_send_request. Nothing is sent.

◆ RCLC_SERVICE_TYPED_ERR_RESPONSE_DESERIALIZE

#define RCLC_SERVICE_TYPED_ERR_RESPONSE_DESERIALIZE   -4

<Resp>_deserialize rejected the reply bytes. The response struct is left zero-initialised rather than half-filled.

◆ RCLC_SERVICE_TYPED_ERR_RESPONSE_SERIALIZE

#define RCLC_SERVICE_TYPED_ERR_RESPONSE_SERIALIZE   -2

<Resp>_serialize did not fit the executor's reply buffer. No reply is sent — a truncated CDR payload is a wrong answer, not a partial one.

◆ RCLC_SERVICE_TYPED_OK

#define RCLC_SERVICE_TYPED_OK   0

Typed glue succeeded.

◆ RCLC_SHUTDOWN_CALLBACK_HANDLE_INVALID

#define RCLC_SHUTDOWN_CALLBACK_HANDLE_INVALID   4294967295

The value no successful registration ever produces.

Typedef Documentation

◆ rcl_ret_t

typedef int rcl_ret_t

Return type for nros C API functions.

NOT value-compatible with rcl_ret_t — only OK (0) agrees.

CORRECTED 2026-09-04 (phase-417 W5.b). This said "Compatible with rcl_ret_t for familiarity", which is false for five of six shared codes: ours are NEGATIVE where rcl's are positive.

code ours rcl
OK 0 0
ERROR -1 1
TIMEOUT -2 2
UNSUPPORTED -16 3
INVALID_ARGUMENT -3 11
NOT_INIT -7 101

A ported if (ret == RCL_RET_TIMEOUT) compiled against the old comment and never matched — the "compiles and differs" shape RFC-0089 forbids, arriving through a doc comment rather than a signature.

<rclc/detail/rcl_compat.h> maps rcl's constant SPELLINGS onto these values. The values are deliberately NOT renumbered: doing so would silently flip the meaning of every stored return code across the C, C++ and Rust FFI seams.

◆ rclc_accepted_callback_t

typedef void(* rclc_accepted_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, void *context)

Goal accepted callback type.

Invoked after the arena has sent the accept reply to the client. Use this to kick off goal execution.

◆ rclc_cancel_callback_t

typedef enum rclc_cancel_response_t(* rclc_cancel_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, void *context)

Cancel request callback type.

Invoked when a client requests cancellation of an accepted goal. Return RCLC_CANCEL_ACCEPT or RCLC_CANCEL_REJECT.

◆ rclc_deadline_policy_t

typedef uint8_t rclc_deadline_policy_t

◆ rclc_endpoint_info_visit_fn

typedef bool(* rclc_endpoint_info_visit_fn) (void *ctx, const struct rclc_endpoint_info_t *info)

phase-381 W4 — visit one endpoint. Return false to stop.

◆ rclc_event_liveliness_changed_cb_t

typedef void(* rclc_event_liveliness_changed_cb_t) (struct rcl_subscription_t *sub, struct rclc_liveliness_changed_status_t status, void *user_context)

Callback for NROS_EVENT_LIVELINESS_CHANGED.

◆ rclc_event_publisher_count_cb_t

typedef void(* rclc_event_publisher_count_cb_t) (struct rcl_publisher_t *pub_, struct rclc_count_status_t status, void *user_context)

Callback for NROS_EVENT_LIVELINESS_LOST, NROS_EVENT_OFFERED_DEADLINE_MISSED (publisher side).

◆ rclc_event_subscriber_count_cb_t

typedef void(* rclc_event_subscriber_count_cb_t) (struct rcl_subscription_t *sub, struct rclc_count_status_t status, void *user_context)

Callback for NROS_EVENT_REQUESTED_DEADLINE_MISSED, NROS_EVENT_MESSAGE_LOST (subscriber side).

◆ rclc_executor_trigger_t

typedef bool(* rclc_executor_trigger_t) (const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)

Trigger function type for executor.

A trigger function receives the executor's registered handles, each carrying its entity pointer and whether it has data this cycle. It returns true if the executor should process callbacks.

Mirrors rclc's rclc_executor_trigger_t (bool (*)(rclc_executor_handle_t *, unsigned int, void *)), with our narrower handle element and a size_t count.

Parameters

  • handles - Pointer to an array of size registered handles
  • size - Number of elements in the array
  • obj - User-provided object pointer (rclc's trigger_object)

Returns

  • true if executor should process callbacks
  • false if executor should skip processing

◆ rclc_feedback_callback_t

typedef void(* rclc_feedback_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, const uint8_t *feedback, size_t feedback_len, void *context)

Feedback callback type (for client).

◆ rclc_goal_callback_t

typedef enum rclc_goal_response_t(* rclc_goal_callback_t) (struct rcl_action_server_t *server, const struct rclc_goal_handle_t *goal, const uint8_t *goal_request, size_t goal_len, void *context)

Goal request callback type.

Invoked when a client sends a new goal. Return RCLC_GOAL_REJECT, RCLC_GOAL_ACCEPT_AND_EXECUTE, or RCLC_GOAL_ACCEPT_AND_DEFER.

◆ rclc_goal_response_callback_t

typedef void(* rclc_goal_response_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, bool accepted, void *context)

Goal response callback type (for async client). Called when the action server accepts or rejects a goal.

◆ rclc_guard_condition_callback_t

typedef void(* rclc_guard_condition_callback_t) (void *context)

Guard condition callback type.

◆ rclc_lifecycle_callback_t

typedef uint8_t(* rclc_lifecycle_callback_t) (void *context)

C callback type for a lifecycle transition: uint8_t callback(void *context).

The return value is a REP-2002 TransitionResult ([RCLC_LIFECYCLE_RET_OK] = 0, [RCLC_LIFECYCLE_RET_FAILURE] = 1, [RCLC_LIFECYCLE_RET_ERROR] = 2). context is the pointer most recently handed to a nros_lifecycle_register_on_* / nros_executor_lifecycle_register_on_* call — all six slots on one state machine share a single context.

NULL clears the slot.

Issue 0792: this alias is declared HERE rather than reusing nros_node::lifecycle::LifecycleCallbackFnCtx because cbindgen runs with parse_deps = false. A cross-crate Option<LifecycleCallbackFnCtx> in an extern "C" signature is unresolvable to it, so it emitted an OPAQUE struct Option_LifecycleCallbackFnCtx and passed it BY VALUE — a C translation unit could not form the argument, and all twelve *_register_on_* entry points were uncallable from C. A local Option<fn> alias renders as a plain nullable function pointer (the same shape rclc_guard_condition_callback_t and rclc_timer_callback_with_context_t already use, and the same one the C++ shim's nros_cpp_lifecycle_callback_t uses). The ABI is unchanged: a nullable extern "C" fn is one pointer either way.

◆ rclc_message_deserialize_fn_t

typedef int32_t(* rclc_message_deserialize_fn_t) (const uint8_t *buffer, size_t len, void *msg)

A type-erased CDR deserialiser for one message type (phase-492 W8).

Reads buffer[..len] into msg (a pointer to the generated struct, its strings and sequences wired to caller memory) and returns 0; a malformed sample or a field that does not fit its capacity returns nonzero and the field is not written. Never allocates.

◆ rclc_message_serialize_fn_t

typedef int32_t(* rclc_message_serialize_fn_t) (const void *msg, uint8_t *buffer, size_t capacity, size_t *out_len)

A type-erased CDR serialiser for one message type (phase-492 W8).

Writes msg (a pointer to the generated struct) into buffer[..capacity] with its 4-byte encapsulation header, stores the byte count in *out_len, and returns 0; any failure (buffer too small, a field past its .msg bound, a NULL data with a nonzero size) returns nonzero. Never allocates.

◆ rclc_names_and_types_visit_fn

typedef bool(* rclc_names_and_types_visit_fn) (void *ctx, const char *name, const char *const *types, size_t types_count)

phase-381 W4 — visit one name and the types on it.

types_count may legitimately be 0 on a partially discovered graph: reporting the name without a type beats dropping it. Strings are BORROWED. Return false to stop.

◆ rclc_node_visit_fn

typedef bool(* rclc_node_visit_fn) (void *ctx, const char *node_name, const char *node_namespace, const char *enclave)

phase-381 W4 — visit one node on the graph.

node_namespace is a ROS namespace ("/", "/demo"). enclave is NULL where the backend does not track one, which is what lets one call answer both rmw_get_node_names and rmw_get_node_names_with_enclaves.

Every string is BORROWED for the duration of the call — copy anything you keep. Return false to stop the enumeration early.

◆ rclc_response_callback_t

typedef void(* rclc_response_callback_t) (const uint8_t *response, size_t response_len, void *context)

Service-client response callback type (Phase 82).

Invoked by the executor's spin_some dispatch when a previously-sent request has its response delivered. The CDR bytes are owned by the arena entry's reply buffer for the duration of the call — copy if you need to keep them.

◆ rclc_result_callback_t

typedef void(* rclc_result_callback_t) (const struct rclc_goal_uuid_t *goal_uuid, enum rclc_goal_status_t status, const uint8_t *result, size_t result_len, void *context)

Result callback type (for client).

◆ rclc_sched_class_t

typedef uint8_t rclc_sched_class_t

◆ rclc_sched_context_id_t

typedef uint8_t rclc_sched_context_id_t

Identifier of a registered scheduling context. 0 is the auto-created default Fifo SC. Mirrors nros_node::executor::sched_context::SchedContextId.

◆ rclc_sched_priority_t

typedef uint8_t rclc_sched_priority_t

◆ rclc_service_raw_callback_t

typedef bool(* rclc_service_raw_callback_t) (const uint8_t *request_data, size_t request_len, uint8_t *response_data, size_t response_capacity, size_t *response_len, void *context)

Service server callback function type.

Parameters

  • request_data - Pointer to CDR-serialized request data
  • request_len - Length of request data in bytes
  • response_data - Pointer to buffer for CDR-serialized response
  • response_capacity - Capacity of response buffer
  • response_len - Output: actual length of response data written
  • context - User-provided context pointer

Returns

  • true if the request was handled successfully
  • false if there was an error handling the request

◆ rclc_shutdown_callback_handle_t

Handle to a registered shutdown hook.

Returned by nros_executor_add_{pre,on}_shutdown_callback and consumed by the matching remove. Opaque: the only operations are "pass it back" and "compare against `RCLC_SHUTDOWN_CALLBACK_HANDLE_INVALID`".

◆ rclc_shutdown_callback_t

typedef void(* rclc_shutdown_callback_t) (void *context)

Shutdown-hook callback type.

Parameters

  • context - User-provided context pointer, handed back unchanged.

◆ rclc_subscription_callback_with_context_t

typedef void(* rclc_subscription_callback_with_context_t) (const void *msg, void *context)

phase-417 W5.a — a subscription callback that receives the DESERIALISED message, the shape rclc delivers (rclc_subscription_callback_with_context_t, the alias <rclc/executor.h> declares).

msg is the caller's own storage, populated by the subscription type's deserialiser immediately before the call. It is valid for the duration of the call and is overwritten by the next dispatch — copy out anything retained.

◆ rclc_subscription_info_callback_t

typedef void(* rclc_subscription_info_callback_t) (const uint8_t *data, size_t len, const uint8_t *attachment, size_t attachment_len, void *context)

Subscription callback that also receives the sample's wire attachment (Phase 189.M3.4 — the C analog of the Rust node.subscription(t).generic(..).message_info() builder path). Used by rclc_executor_add_subscription_raw_with_info.

Parameters

  • data / len — received CDR bytes.
  • attachment / attachment_len — the sample's wire attachment (attachment_len == 0 ⇒ none). Cross-RMW bridges read the bridge_origin tag from it. Valid only during the call.
  • context — user-provided context pointer.

◆ rclc_subscription_raw_callback_t

typedef void(* rclc_subscription_raw_callback_t) (const uint8_t *data, size_t len, void *context)

Subscription callback function type.

Parameters

  • data - Pointer to received CDR-serialized message data
  • len - Length of data in bytes
  • context - User-provided context pointer

◆ rclc_subscription_validated_callback_t

typedef void(* rclc_subscription_validated_callback_t) (const uint8_t *data, size_t len, int64_t gap, bool duplicate, int8_t crc_valid, void *context)

phase-492 W4 — callback for a VALIDATED raw subscription (rclc_executor_add_subscription_raw_validated): the CDR bytes plus the sample's E2E integrity status as three scalars — the sequence gap since the previous sample, whether it is a duplicate, and crc_valid (1 valid, 0 invalid, -1 no CRC carried). Scalars rather than a struct pointer so the executor hands them over without a wrapper holding state (RFC-0019/0020).

◆ rclc_timer_callback_with_context_t

typedef void(* rclc_timer_callback_with_context_t) (struct rcl_timer_t *timer, void *context)

Timer callback function type.

Parameters

  • timer - Pointer to the timer that triggered
  • context - User-provided context pointer

◆ rmw_publisher_allocation_t

upstream rmw's publisher pre-allocation handle, declared INCOMPLETE (phase-492 W8).

rcl_publish(&pub, &msg, NULL) compiles because a pointer to an incomplete type is fine; declaring one (rmw_publisher_allocation_t a;) does not, because nano-ros has no pre-allocation to hand out: the transmit buffer is already bounded at build time. Pass NULL.

◆ rmw_subscription_allocation_t

upstream rmw's subscription pre-allocation handle, declared INCOMPLETE (phase-492 W8): a pointer to one compiles, so NULL can be passed; declaring one does not. nano-ros has no pre-allocation to hand out.

Enumeration Type Documentation

◆ rcl_clock_type_t

Clock type enumeration.

Enumerator
RCL_CLOCK_UNINITIALIZED 

Uninitialized clock

RCL_ROS_TIME 

ROS time - follows /clock topic if available, otherwise system time

RCL_SYSTEM_TIME 

System time - wall clock time from the operating system

RCL_STEADY_TIME 

Steady time - monotonic clock, not affected by system time changes

◆ rclc_action_client_state_t

Action client state.

Enumerator
RCLC_ACTION_CLIENT_STATE_UNINITIALIZED 

Not initialized

RCLC_ACTION_CLIENT_STATE_INITIALIZED 

Initialized. For a rcl_action_client_t the transport is created by rclc_executor_attach_action_client; for a rclc_polling_action_client_t its ActionClientCore is live in the struct.

RCLC_ACTION_CLIENT_STATE_SHUTDOWN 

Shutdown

◆ rclc_action_server_state_t

Action server state.

Enumerator
RCLC_ACTION_SERVER_STATE_UNINITIALIZED 

Not initialized

RCLC_ACTION_SERVER_STATE_INITIALIZED 

Initialized. For a rcl_action_server_t the transport is created by rclc_executor_attach_action_server; for a rclc_polling_action_server_t its ActionServerCore is live in the struct.

RCLC_ACTION_SERVER_STATE_SHUTDOWN 

Shutdown

◆ rclc_cancel_response_t

Cancel response codes.

Enumerator
RCLC_CANCEL_REJECT 

Reject the cancel request

RCLC_CANCEL_ACCEPT 

Accept the cancel request

◆ rclc_cancel_return_code_t

Phase 122.3.c.6.d — overall cancel-RPC return code. Distinct from the per-goal rclc_cancel_response_t (ACCEPT/REJECT) used by the L2 callback path. These four discriminants mirror nros_core::CancelReturnCode and the action_msgs/srv/CancelGoal wire-CDR return_code field. (Issue 0796 — the Rust type was called CancelResponse until it was split; this pair of C names is what the Rust names now follow.)

Enumerator
RCLC_CANCEL_RC_OK 
RCLC_CANCEL_RC_REJECTED 
RCLC_CANCEL_RC_UNKNOWN_GOAL 
RCLC_CANCEL_RC_GOAL_TERMINATED 

◆ rclc_client_state_t

Client state

Enumerator
RCLC_CLIENT_STATE_UNINITIALIZED 

Not initialized

RCLC_CLIENT_STATE_INITIALIZED 

Initialized — metadata stored, not yet registered with an executor.

RCLC_CLIENT_STATE_REGISTERED 

Registered with an executor and ready for send_request_async / call.

RCLC_CLIENT_STATE_SHUTDOWN 

Shutdown

◆ rclc_clock_state_t

Clock state enumeration.

Enumerator
RCLC_CLOCK_STATE_UNINITIALIZED 

Not initialized

RCLC_CLOCK_STATE_READY 

Initialized and ready

RCLC_CLOCK_STATE_SHUTDOWN 

Shutdown

◆ rclc_deadline_policy_t

Deadline interpretation policy. Mirrors nros_node::executor::sched_context::DeadlinePolicy.

Enumerator
RCLC_DEADLINE_POLICY_RELEASED 
RCLC_DEADLINE_POLICY_ACTIVATED 
RCLC_DEADLINE_POLICY_INHERITED 

◆ rclc_executor_handle_invocation_t

Callback invocation mode

Enumerator
ON_NEW_DATA 

Only invoke callback when new data is available

ALWAYS 

Always invoke callback (even with NULL data)

◆ rclc_executor_semantics_t

Executor data communication semantics

Defines when data is taken from DDS during spin operations.

Enumerator
RCLCPP_EXECUTOR 

RCLCPP executor semantics: Data is taken from DDS just before the corresponding callback is called.

LET 

Logical Execution Time (LET) semantics: At one sampling point, new data of all ready subscriptions are taken from DDS. During sequential processing, the data from that sampling point is used. New data arriving after the sampling point is not considered until the next spin iteration.

◆ rclc_executor_state_t

Executor state

Enumerator
RCLC_EXECUTOR_STATE_UNINITIALIZED 

Not initialized

RCLC_EXECUTOR_STATE_INITIALIZED 

Initialized and ready

RCLC_EXECUTOR_STATE_SPINNING 

Currently spinning

RCLC_EXECUTOR_STATE_SHUTDOWN 

Shutdown

◆ rclc_goal_response_t

Goal response codes for goal request handling.

Enumerator
RCLC_GOAL_REJECT 

Reject the goal

RCLC_GOAL_ACCEPT_AND_EXECUTE 

Accept the goal and start executing immediately

RCLC_GOAL_ACCEPT_AND_DEFER 

Accept the goal but defer execution

◆ rclc_goal_status_t

Goal status enumeration.

Compatible with action_msgs/msg/GoalStatus values.

Enumerator
RCLC_GOAL_STATUS_UNKNOWN 

Goal state is unknown

RCLC_GOAL_STATUS_ACCEPTED 

Goal was accepted and is pending execution

RCLC_GOAL_STATUS_EXECUTING 

Goal is currently being executed

RCLC_GOAL_STATUS_CANCELING 

Goal is being canceled

RCLC_GOAL_STATUS_SUCCEEDED 

Goal completed successfully

RCLC_GOAL_STATUS_CANCELED 

Goal was canceled

RCLC_GOAL_STATUS_ABORTED 

Goal was aborted (failed)

◆ rclc_guard_condition_state_t

Guard condition state.

Enumerator
RCLC_GUARD_CONDITION_STATE_UNINITIALIZED 

Not initialized

RCLC_GUARD_CONDITION_STATE_INITIALIZED 

Initialized and ready

RCLC_GUARD_CONDITION_STATE_SHUTDOWN 

Shutdown

◆ rclc_node_state_t

Node state

Enumerator
RCLC_NODE_STATE_UNINITIALIZED 

Not initialized

RCLC_NODE_STATE_INITIALIZED 

Initialized and ready

RCLC_NODE_STATE_SHUTDOWN 

Shutdown

◆ rclc_publisher_state_t

Publisher state

Enumerator
RCLC_PUBLISHER_STATE_UNINITIALIZED 

Not initialized

RCLC_PUBLISHER_STATE_INITIALIZED 

Initialized and ready

RCLC_PUBLISHER_STATE_SHUTDOWN 

Shutdown

◆ rclc_qos_durability_t

QoS durability policy

Enumerator
RCLC_QOS_DURABILITY_VOLATILE 

Volatile - no persistence

RCLC_QOS_DURABILITY_TRANSIENT_LOCAL 

Transient local - persist for late joiners

RCLC_QOS_DURABILITY_SYSTEM_DEFAULT 

The caller stated no durability policy — the middleware chose. Upstream's RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT.

RCLC_QOS_DURABILITY_UNKNOWN 

The backend could not determine this policy — an ABSENCE, never a request. Upstream's RMW_QOS_POLICY_DURABILITY_UNKNOWN.

◆ rclc_qos_history_t

QoS history policy

Enumerator
RCLC_QOS_HISTORY_KEEP_LAST 

Keep last N samples

RCLC_QOS_HISTORY_KEEP_ALL 

Keep all samples

RCLC_QOS_HISTORY_SYSTEM_DEFAULT 

The caller stated no history policy — the middleware chose. Upstream's RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT.

RCLC_QOS_HISTORY_UNKNOWN 

The backend could not determine this policy — an ABSENCE, never a request. Upstream's RMW_QOS_POLICY_HISTORY_UNKNOWN.

◆ rclc_qos_liveliness_t

QoS liveliness policy. Phase 109 — matches DDS LIVELINESS.

Enumerator
RCLC_QOS_LIVELINESS_NONE 

No liveliness assertion or tracking.

This is ALSO the "nobody stated a liveliness policy" slot — it is discriminant 0, the value the RMW ABI spells NROS_RMW_LIVELINESS_SYSTEM_DEFAULT, and a backend that sees it omits the DDS call entirely. So this enum gains no separate SYSTEM_DEFAULT: it would be a second name for a value that already has one, which is how a vocabulary starts disagreeing with itself.

RCLC_QOS_LIVELINESS_AUTOMATIC 

Backend's keepalive task asserts liveliness automatically.

RCLC_QOS_LIVELINESS_MANUAL_BY_TOPIC 

Application calls assert_liveliness() per topic explicitly.

RCLC_QOS_LIVELINESS_MANUAL_BY_NODE 

Application calls assert_liveliness() at the node level.

RCLC_QOS_LIVELINESS_UNKNOWN 

The backend could not determine this policy — an ABSENCE, never a request. Upstream's RMW_QOS_POLICY_LIVELINESS_UNKNOWN.

◆ rclc_qos_reliability_t

QoS reliability policy

Enumerator
RCLC_QOS_RELIABILITY_BEST_EFFORT 

Best effort delivery - no guarantees

RCLC_QOS_RELIABILITY_RELIABLE 

Reliable delivery - retransmit if needed

RCLC_QOS_RELIABILITY_SYSTEM_DEFAULT 

The caller stated no reliability policy — the middleware chose. Upstream's RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT.

RCLC_QOS_RELIABILITY_UNKNOWN 

The backend could not determine this policy — an ABSENCE, never a request. Upstream's RMW_QOS_POLICY_RELIABILITY_UNKNOWN.

◆ rclc_sched_class_t

Scheduling class — picks the runtime queue + selection policy. Mirrors nros_node::executor::sched_context::SchedClass.

Enumerator
RCLC_SCHED_CLASS_FIFO 
RCLC_SCHED_CLASS_EDF 
RCLC_SCHED_CLASS_SPORADIC 
RCLC_SCHED_CLASS_BEST_EFFORT 
RCLC_SCHED_CLASS_TIME_TRIGGERED 

◆ rclc_sched_priority_t

Criticality bucket. Lower numeric value = higher priority. Mirrors nros_node::executor::sched_context::Priority.

Enumerator
RCLC_SCHED_PRIORITY_CRITICAL 
RCLC_SCHED_PRIORITY_NORMAL 
RCLC_SCHED_PRIORITY_BEST_EFFORT 

◆ rclc_service_state_t

Service server state

Enumerator
RCLC_SERVICE_STATE_UNINITIALIZED 

Not initialized

RCLC_SERVICE_STATE_INITIALIZED 

Initialized. For a rcl_service_t the server is created later, by rclc_executor_add_service_raw, inside the executor arena. For a rclc_polling_service_t the server is live in the struct's storage.

RCLC_SERVICE_STATE_SHUTDOWN 

Shutdown

◆ rclc_subscription_state_t

Subscription state

Enumerator
RCLC_SUBSCRIPTION_STATE_UNINITIALIZED 

Not initialized

RCLC_SUBSCRIPTION_STATE_INITIALIZED 

Initialized. For a rcl_subscription_t the subscriber entity is created later, by nros_executor_add_subscription_*, inside the executor arena. For a rclc_polling_subscription_t the subscriber is live in the struct's own storage.

RCLC_SUBSCRIPTION_STATE_SHUTDOWN 

Shutdown

◆ rclc_support_state_t

Support context state

Enumerator
RCLC_SUPPORT_STATE_UNINITIALIZED 

Not initialized

RCLC_SUPPORT_STATE_INITIALIZED 

Initialized and ready

RCLC_SUPPORT_STATE_SHUTDOWN 

Shutdown

◆ rclc_timer_state_t

Timer state

Enumerator
RCLC_TIMER_STATE_UNINITIALIZED 

Not initialized

RCLC_TIMER_STATE_RUNNING 

Initialized and running

RCLC_TIMER_STATE_CANCELED 

Initialized but canceled

RCLC_TIMER_STATE_SHUTDOWN 

Shutdown

Function Documentation

◆ nros_c_support_init_baked()

rcl_ret_t nros_c_support_init_baked ( struct rclc_support_t *  support,
int  argc,
const char *const *  argv,
const struct rcl_allocator_t *  allocator,
const char *  rmw,
const char *  locator,
uint8_t  domain_id 
)

[rclc_support_init] with the image's BAKED connect rungs — the seam <rclc/detail/baked_rmw.h>'s rclc_support_init macro forwards to: the RMW selector (NROS_ENTRY_RMW, issue 1531) and, since phase-499 W2, the locator and domain (NROS_ENTRY_LOCATOR / NROS_ENTRY_DOMAIN_ID). Those are macros defined in the CALLER's translation unit — a cargo-rooted C image bakes them there (nros_cc_flags::entry_config) — so only a header can carry them here; without this a C image calling rclc's form dialled the backend default (measured: every bare-metal C cell, ConnectionFailed), while C++'s inline init_in() read them. They are the BAKED rung: the hosted environment still wins in the resolver. Not for callers: an application names a backend with [rclc_support_init_rmw].

Safety

As [rclc_support_init]; rmw and locator NULL or NUL-terminated.

◆ nros_platform_clock_ns()

uint64_t nros_platform_clock_ns ( void  )
extern

Monotonic nanoseconds since a platform-defined epoch (RFC-0073).

◆ nros_platform_critical_section_acquire()

uint32_t nros_platform_critical_section_acquire ( void  )
extern

◆ nros_platform_critical_section_release()

void nros_platform_critical_section_release ( uint32_t  token)
extern

◆ nros_platform_heap_total_bytes()

size_t nros_platform_heap_total_bytes ( void  )
extern

◆ nros_platform_heap_used_bytes()

size_t nros_platform_heap_used_bytes ( void  )
extern

◆ nros_platform_sleep_us()

void nros_platform_sleep_us ( size_t  us)
extern

Sleep at least us microseconds.

◆ nros_platform_time_now_ns()

uint64_t nros_platform_time_now_ns ( void  )
extern

Nanoseconds since the Unix epoch (issue 0532).

ONE symbol, replacing the time_since_epoch_{secs,nanos} pair. Those are RETIRED — nothing defines them any more, so a reference here is not a deprecation warning but an undefined symbol at link time.

◆ rcl_action_client_fini()

rcl_ret_t rcl_action_client_fini ( struct rcl_action_client_t *  client,
struct rcl_node_t *  node 
)

Finalize an action client.

Issue 1609 — fini does NOT remove the client from an executor; its arena entry holds this struct as its callback context. Call rclc_executor_remove_action_client(executor, client) first, which drops the entry (the action leaves the graph) and brings the executor's handle_count back down.

◆ rcl_action_client_get_action_name()

const char * rcl_action_client_get_action_name ( const struct rcl_action_client_t *  client)

Read back the action name this client was created on.

rcl's rcl_action_client_get_action_name, and the third of the C surface's name accessors — rcl_service_get_service_name, rcl_subscription_get_topic_name and rcl_publisher_get_topic_name already had this shape, and the action client and server were the two entities that did not (phase-417 W4.b, ledger row c:action_client_get_action_name). The name is the caller's own string, copied NUL-terminated into the handle at init, so this hands back a pointer into the handle and costs nothing.

Parameters

  • client - Pointer to an action client

Returns

  • Pointer to the action name (NUL-terminated), or NULL when client is NULL or was never initialised. A polled client is its own type since phase-487 W4 (rclc_polling_action_client_t) and keeps no name.

◆ rcl_action_client_get_default_options()

struct rcl_action_client_options_t rcl_action_client_get_default_options ( void  )

Get a zero-initialised [rcl_action_client_options_t] (sched_context = 0).

◆ rcl_action_client_init()

rcl_ret_t rcl_action_client_init ( struct rcl_action_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_action_type_t *  type_info,
const char *  action_name,
const struct rcl_action_client_options_t *  options 
)

Initialize an action client — rcl's signature (phase-492 W1.b): rcl_action_client_init(&client, &node, ROSIDL_GET_ACTION_TYPE_SUPPORT(...), "name", &options). The type support is our descriptor (ROSIDL_GET_ACTION_TYPE_SUPPORT yields its address, RFC-0089 2026-10-12). options may be NULL for the defaults; a non-zero sched_context is applied by rclc_executor_attach_action_client once the handle exists.

Safety

All non-NULL pointers must be valid and the node initialized; options may be NULL.

◆ rcl_action_get_zero_initialized_client()

struct rcl_action_client_t rcl_action_get_zero_initialized_client ( void  )

Get a zero-initialized action client.

◆ rcl_action_get_zero_initialized_server()

struct rcl_action_server_t rcl_action_get_zero_initialized_server ( void  )

Get a zero-initialized action server.

improper_ctypes_definitions is silenced because the inline opaque handle stores a function-pointer field whose parameter signature references a runtime-internal type. The pointer itself is C-ABI safe; the C API never lets callers invoke through it directly.

◆ rcl_action_server_fini()

rcl_ret_t rcl_action_server_fini ( struct rcl_action_server_t *  server,
struct rcl_node_t *  node 
)

Finalize an action server.

Issue 1609 — fini does NOT remove the server from an executor. It is handed only the entity, and an executor-registered server's arena entry (its three service servers, two publishers and the callback context, which is server itself) is undone by rclc_executor_remove_action_server(executor, server), which also brings the executor's handle_count back down. Call that first; a server that is finalised while still registered keeps answering goals into this struct until rclc_executor_fini.

◆ rcl_action_server_get_action_name()

const char * rcl_action_server_get_action_name ( const struct rcl_action_server_t *  server)

Read back the action name this server was created on.

rcl's rcl_action_server_get_action_name, the server twin of [rcl_action_client_get_action_name](crate::action::client::rcl_action_client_get_action_name) — phase-417 W4.b, ledger row c:action_server_get_action_name. The name is the caller's own string, copied NUL-terminated into the handle at init, so this hands back a pointer into the handle and costs nothing.

Parameters

  • server - Pointer to an action server

Returns

  • Pointer to the action name (NUL-terminated), or NULL when server is NULL or was never initialised. Both live tiers answer — L2 (callback, INITIALIZED) and L1 (polling), for the same reason rcl_service_t::is_usable covers both.

◆ rcl_action_server_get_default_options()

struct rcl_action_server_options_t rcl_action_server_get_default_options ( void  )

Get a zero-initialised [rcl_action_server_options_t] (sched_context = 0).

◆ rcl_client_fini()

rcl_ret_t rcl_client_fini ( struct rcl_client_t *  client,
struct rcl_node_t *  node 
)

Finalize a service client.

Phase 82: the underlying transport handle lives in the executor's arena and is dropped automatically when the executor is finalised. This function only resets the C-side metadata + internal blob.

Parameters

  • client - Pointer to an initialized client

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if client is NULL
  • RCL_RET_NOT_INIT if not initialized

◆ rcl_client_get_default_options()

struct rcl_client_options_t rcl_client_get_default_options ( void  )

Get a zero-initialised [rcl_client_options_t] (sched_context = 0).

◆ rcl_client_get_service_name()

const char * rcl_client_get_service_name ( const struct rcl_client_t *  client)

Get the service name of a client.

Parameters

  • client - Pointer to a client

Returns

  • Pointer to service name (null-terminated), or NULL if the handle is not usable (see rcl_client_t::is_usable) or NULL

◆ rcl_client_is_valid()

bool rcl_client_is_valid ( const struct rcl_client_t *  client)

Is this client handle usable?

rcl's rcl_client_is_valid, whose contract is "true for any handle that can be used" — the ported idiom is a guard. See rcl_client_t::is_usable for which states those are.

Parameters

  • client - Pointer to a client

Returns

  • true if usable, false if finalised, uninitialised or NULL

◆ rcl_clock_fini()

rcl_ret_t rcl_clock_fini ( struct rcl_clock_t *  clock)

Finalize a clock.

◆ rcl_clock_get_now()

rcl_ret_t rcl_clock_get_now ( const struct rcl_clock_t *  clock,
int64_t *  nanoseconds 
)

Get the current time from a clock as a nanosecond count — rcl's contract (rcl_time_point_value_t *). phase-492 W1.b: was rclc_clock_get_now_ns.

◆ rcl_clock_init()

rcl_ret_t rcl_clock_init ( enum rcl_clock_type_t  clock_type,
struct rcl_clock_t *  clock,
struct rcl_allocator_t *  allocator 
)

Initialize a clock — rcl's signature (phase-492 W1.b): rcl_clock_init(type, &clock, &allocator). allocator must be NULL or rcl_get_default_allocator()'s; a clock allocates nothing.

Safety

clock must be valid for writes; allocator NULL or readable.

◆ rcl_clock_time_started()

bool rcl_clock_time_started ( const struct rcl_clock_t *  clock)

Whether the clock has produced a time yet.

Mirrors rcl_clock_time_started, including its implementation: read the clock and report whether the value is non-zero. For a ROS-time clock that is the "enabled, but no `/clock` sample has arrived" state — the one rcl_enable_ros_time_override leaves behind — and for a system or steady clock it is true as soon as the clock is valid.

◆ rcl_disable_ros_time_override()

rcl_ret_t rcl_disable_ros_time_override ( const struct rcl_clock_t *  clock)

Disable the ROS time override; the clock reads the system clock again.

Mirrors rcl_disable_ros_time_override, and nros_core::Clock:: clear_ros_time_override underneath. The stored time does not survive: with one piece of state there is nowhere for an inert value to live, so re-enabling starts from 0 again.

◆ rcl_enable_ros_time_override()

rcl_ret_t rcl_enable_ros_time_override ( const struct rcl_clock_t *  clock)

Enable the ROS time override on a RCL_ROS_TIME clock.

Mirrors rcl_enable_ros_time_override. If no override is active yet the clock starts at time 0 — the state rcl reports as "not started" (rcl_clock_time_started), i.e. enabled but waiting for the first /clock sample. An already-active override keeps its value.

◆ rcl_get_default_allocator()

struct rcl_allocator_t rcl_get_default_allocator ( void  )

The default allocator: rcl's spelling, our envelope. Its functions allocate nothing (NULL from every allocating call). Pass it, or NULL, to any init that takes an allocator.

◆ rcl_get_zero_initialized_client()

struct rcl_client_t rcl_get_zero_initialized_client ( void  )

Get a zero-initialized client.

◆ rcl_get_zero_initialized_guard_condition()

struct rcl_guard_condition_t rcl_get_zero_initialized_guard_condition ( void  )

Get a zero-initialized guard condition.

◆ rcl_get_zero_initialized_node()

struct rcl_node_t rcl_get_zero_initialized_node ( void  )

Get a zero-initialized node.

Safety

Returns a stack-allocated struct that must be initialized before use.

◆ rcl_get_zero_initialized_publisher()

struct rcl_publisher_t rcl_get_zero_initialized_publisher ( void  )

Get a zero-initialized publisher.

◆ rcl_get_zero_initialized_service()

struct rcl_service_t rcl_get_zero_initialized_service ( void  )

Get a zero-initialized service server.

◆ rcl_get_zero_initialized_subscription()

struct rcl_subscription_t rcl_get_zero_initialized_subscription ( void  )

Get a zero-initialized subscription.

◆ rcl_get_zero_initialized_timer()

struct rcl_timer_t rcl_get_zero_initialized_timer ( void  )

Get a zero-initialized timer.

◆ rcl_guard_condition_fini()

rcl_ret_t rcl_guard_condition_fini ( struct rcl_guard_condition_t *  guard)

Finalize a guard condition.

IDEMPOTENT: a zero-initialised or already-finalised handle is not an error and returns RCL_RET_OK. A NULL pointer is still RCL_RET_INVALID_ARGUMENT.

That is rcl's contract, MEASURED rather than assumed (phase-417 stage 3 — the ledger row carried an explicit evidence bound because the host it was written on had only the Humble headers, which do not state the guarantee in words). rcl/src/rcl/guard_condition.c @ humble:

rcl_guard_condition_fini(rcl_guard_condition_t * guard_condition)
{
RCL_CHECK_ARGUMENT_FOR_NULL(guard_condition, RCL_RET_INVALID_ARGUMENT);
rcl_ret_t result = RCL_RET_OK;
if (guard_condition->impl) { … }
return result;
}

so NULL errors and impl == NULL — a zero-initialised or already-finalised handle — returns OK. Ours returned RCL_RET_NOT_INIT for the second case, and since rcl_*_fini is RCL_WARN_UNUSED upstream, a ported cleanup path that checks its return reported a shutdown failure that had not happened.

◆ rcl_is_enabled_ros_time_override()

rcl_ret_t rcl_is_enabled_ros_time_override ( const struct rcl_clock_t *  clock,
bool *  is_enabled 
)

Whether the ROS time override is in effect.

Mirrors rcl_is_enabled_ros_time_override. Writes is_enabled only on RCL_RET_OK.

◆ rcl_node_fini()

rcl_ret_t rcl_node_fini ( struct rcl_node_t *  node)

Finalize a node.

Parameters

  • node - Pointer to an initialized node

Returns

  • RCL_RET_OK on success, AND for a node that was never initialised or is already finalised — fini is IDEMPOTENT (phase-417 stage 3, the same sweep as rcl_guard_condition_fini). rcl/src/rcl/node.c @ humble says it in words: if (!node->impl) { // Repeat calls to fini or calling fini on a zero initialized node is ok. return RCL_RET_OK; }. Ours returned RCL_RET_NOT_INIT, so a ported cleanup path that checks the return — rcl_node_fini is RCL_WARN_UNUSED upstream — reported a shutdown failure that had not happened.
  • RCL_RET_INVALID_ARGUMENT if node is NULL

Safety

  • node must be a valid pointer to an initialized rcl_node_t

◆ rcl_node_get_default_options()

struct rcl_node_options_t rcl_node_get_default_options ( void  )

Get a zero-initialised rcl_node_options_t.

All fields default to "inherit" — rmw_name_len = 0, locator_len = 0, domain_id_override = NROS_DOMAIN_ID_INHERIT, sched_context_id = 0. Callers populate only the fields they want to override.

◆ rcl_node_get_domain_id()

rcl_ret_t rcl_node_get_domain_id ( const struct rcl_node_t *  node,
size_t *  domain_id 
)

The ROS domain this node's entities are declared on.

rcl's rcl_node_get_domain_id(node, size_t *domain_id). Gap c:node_get_domain_id records why it was missing: the domain is an INPUT to rclc_support_init and could not be read back, while on a device the value that actually won came from the boot ladder.

So this forwards to resolve_session_and_domain — the one place the ladder is decoded (per-node override → C-ABI byte → the session's own domain). Re-deriving it here is precisely issue 0972's defect: the same decode at a third call site, where NROS_DOMAIN_ID_EXPLICIT_ZERO (255) reads as an out-of-range domain and plain 0 reads as domain 0 rather than "unset".

Out-param + status rather than a bare return, because this genuinely can fail to answer — an uninitialised support context, a node whose slot names no session on its executor, or a domain byte above DOMAIN_ID_MAX all have no domain to report, and 0 is a legal domain that must not stand in for any of them. (Issue 1386: this said "a retired node slot", which is not one of them — rcl_node_fini retires the phase-379 W4 GENERATION, and nothing on this path reads it. What the executor lookup can fail on is a slot that names no NodeRecord.)

Returns RCL_RET_UNSUPPORTED in a build with no RMW (rmw-cffi off): there is no session, so there is no resolved domain to read.

Safety

  • node must be NULL or point to a valid rcl_node_t.
  • domain_id must be NULL or writable.

◆ rcl_node_get_name()

const char * rcl_node_get_name ( const struct rcl_node_t *  node)

Get the node name.

Parameters

  • node - Pointer to an initialized node

Returns

  • Pointer to the node name (null-terminated), or NULL if invalid

Safety

  • node must be a valid pointer

◆ rcl_node_get_namespace()

const char * rcl_node_get_namespace ( const struct rcl_node_t *  node)

Get the node namespace.

Parameters

  • node - Pointer to an initialized node

Returns

  • Pointer to the node namespace (null-terminated), or NULL if invalid

Safety

  • node must be a valid pointer

◆ rcl_node_is_valid()

bool rcl_node_is_valid ( const struct rcl_node_t *  node)

Is this node handle usable?

rcl's rcl_node_is_valid. We already had rclc_node_state_t and rclc_support_is_valid for the support object; the node had no predicate that read its own state, which is the whole of gap c:node_is_valid.

Upstream names exactly three invalidity conditions, and they are what this answers — rcl/rcl/node.h @ humble, verbatim: "A node is invalid if: the implementation is <tt>NULL</tt> (rcl_node_init not called or failed); rcl_shutdown has been called since the node has been initialized; the node has been finalized with rcl_node_fini." Two of the three are one field here, so the implementation asks TWO questions:

  • the handle's own state is INITIALIZED — never initialised leaves it UNINITIALIZED, and rcl_node_fini sets SHUTDOWN, which is rcl's first and third conditions on our one state field; and
  • the CONTEXT it names is still valid — rcl's second condition, and the whole of what rcl_node_is_valid_except_context exists to opt OUT of. We decline that name precisely because this one answers the context question. rclc_support_fini drops the inline session, zeroes _opaque and marks the SUPPORT shut down while touching no node, so a node still reads INITIALIZED over a dead session — the guard passed and the next publish dereferenced the zeroed _opaque.

The context is reached by a different route per node SHAPE, and NEITHER route is skipped now (issue 1386): a legacy (rclc_node_init_default) node records its support directly, while rclc_executor_node_init leaves support NULL on purpose (the multi-Node paths key off node_id + executor, phase-156 sub-bug D) and reaches the same support through the executor — crate::executor::executor_context_is_valid, which consults [crate::support::rclc_support_is_valid] rather than re-deriving it. An executor-bound node had NO context check at all before: the arm that stood there compared the slot's current generation with itself.

What this deliberately does NOT claim. C has no move semantics, so rcl_node_t copy = original; is legal and silent, and after rcl_node_fini(&original) the copy still reads INITIALIZED over a live context. This answers true for it — measured, issue 1386 — and so does upstream for the analogous rcl_node_t copy, because a copy carries no evidence that its original was finalised. The phase-379 W4 generation (rclc_node_ref_t) is what catches that class, and it can only catch it where a reference was STORED before the fini: an entity's publisher.node / subscription.node fails its own _fini with RCLC_RET_STALE_NODE. A reference minted from the node inside this call is the current generation by construction, so comparing it with the current generation is constant true — which is what it was.

Safety

  • node must be NULL or point to a valid rcl_node_t.

◆ rcl_publish()

rcl_ret_t rcl_publish ( const struct rcl_publisher_t *  publisher,
const void *  ros_message,
struct rmw_publisher_allocation_t *  allocation 
)

Publish a message — rcl's rcl_publish, serialising through the descriptor this publisher was created with (phase-492 W8).

std_msgs__msg__String msg; // wired by __init_in, or by hand
rcl_publish(&publisher, &msg, NULL);
rcl_ret_t rcl_publish(const struct rcl_publisher_t *publisher, const void *ros_message, struct rmw_publisher_allocation_t *allocation)

ros_message points at the generated struct of the publisher's type. It is serialised by the descriptor's codec into a transmit buffer on this call's stack whose size is BOUNDED AT BUILD TIME, then handed to the backend:

  • the type's own receive bound (serialized_size_max) picks the smaller 256-byte class when it fits;
  • otherwise, or when the sample does not fit the smaller class (a caller that pointed a string at a buffer larger than __Storage sizes), the image's message buffer size (NROS_SUBSCRIPTION_BUFFER_SIZE, the bound the image derives over every type it carries).

No heap, ever (RFC-0105 D10): nothing here, in the serialiser or in the generated struct allocates. A sample larger than the image's message buffer is refused with RCL_RET_ERROR; rclc_publisher_publish_streamed is the entry point for payloads past that bound.

Parameters

  • publisher — an initialised publisher
  • ros_message — the message, of the publisher's type
  • allocation — MUST be NULL. rmw_publisher_allocation_t is declared incomplete: nano-ros has no pre-allocation to offer.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT — a NULL publisher / ros_message, or a non-NULL allocation
  • RCL_RET_NOT_INIT — the publisher is not initialised
  • RCL_RET_UNSUPPORTED — the publisher's descriptor carries no serialiser (one built from type names alone); use rclc_publish_raw
  • RCL_RET_ERROR — the message did not serialise (a field past its .msg bound, a NULL data with nonzero size, or larger than the image's message buffer)
  • RCLC_RET_PUBLISH_FAILED — the backend refused the sample

Safety

  • publisher must point at a valid publisher.
  • ros_message must point at a message of the publisher's type.

◆ rcl_publisher_assert_liveliness()

rcl_ret_t rcl_publisher_assert_liveliness ( const struct rcl_publisher_t *  publisher)

Phase 108.B.7 — manually assert this publisher's liveliness.

Required for entities created with QoS liveliness_kind = RCLC_QOS_LIVELINESS_MANUAL_BY_TOPIC or MANUAL_BY_NODE; there is nothing to assert under AUTOMATIC / NONE, and those answer RCL_RET_OK on every backend.

A BACKEND THAT CANNOT ASSERT REMOTELY ANSWERS RCL_RET_UNSUPPORTED, and this doc said the opposite until the phase-467 RMW gap-closure design study's Row 7. It read "Backends that don't implement manual assertion (XRCE-DDS, zenoh-pico, uORB today) treat this as a no-op and return <tt>RCL_RET_OK</tt>" — an OK from a call that put nothing on the wire, which is the one thing a caller uses this function to find out. cyclonedds does implement it (dds_assert_liveliness renews the writer lease and sends a Heartbeat); zenoh-pico, XRCE-DDS and uORB have no per-topic lease and now say so.

Parameters

  • publisher - Pointer to an initialized publisher

Returns

  • RCL_RET_OK — asserted, or there was nothing to assert
  • RCL_RET_INVALID_ARGUMENT if publisher is NULL
  • RCL_RET_NOT_INIT if not initialized
  • RCL_RET_UNSUPPORTED — a manual liveliness kind on a backend with no per-topic lease. NOT a failure of this call; the entity is fine.
  • RCLC_RET_PUBLISH_FAILED on backend failure

Safety

  • publisher must be a valid pointer to an initialized publisher

◆ rcl_publisher_fini()

rcl_ret_t rcl_publisher_fini ( struct rcl_publisher_t *  publisher,
struct rcl_node_t *  node 
)

Finalize a publisher.

Parameters

  • publisher - Pointer to an initialized publisher

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if publisher is NULL
  • RCL_RET_NOT_INIT if not initialized
  • RCLC_RET_STALE_NODE if the node this publisher was created on has already been finalised — the teardown order was wrong, and nothing is dropped. Undocumented until issue 1386, which is the opposite defect to the one it was filed for: three sites DOCUMENTED a verdict they could not produce while this one produced a verdict it did not document.

Safety

  • publisher must be a valid pointer

◆ rcl_publisher_get_default_options()

struct rcl_publisher_options_t rcl_publisher_get_default_options ( void  )

Get a zero-initialised [rcl_publisher_options_t].

All fields default to "inherit"/"none". Callers populate only the fields they want to override before passing the struct to [rclc_publisher_init_with_options].

◆ rcl_publisher_get_topic_name()

const char * rcl_publisher_get_topic_name ( const struct rcl_publisher_t *  publisher)

Get the topic name of a publisher.

Parameters

  • publisher - Pointer to a publisher

Returns

  • Pointer to topic name (null-terminated), or NULL if the handle is not usable (see rcl_publisher_t::is_usable) or NULL

◆ rcl_publisher_is_valid()

bool rcl_publisher_is_valid ( const struct rcl_publisher_t *  publisher)

Is this publisher handle usable?

rcl's rcl_publisher_is_valid, whose contract is "true for any handle that can be used" — the ported idiom is a guard. See rcl_publisher_t::is_usable for which states those are.

Parameters

  • publisher - Pointer to a publisher

Returns

  • true if usable, false if finalised, uninitialised or NULL

◆ rcl_service_fini()

rcl_ret_t rcl_service_fini ( struct rcl_service_t *  service,
struct rcl_node_t *  node 
)

Finalize a service server.

The server is the executor arena's: remove it with rclc_executor_remove_service first if it was added and the executor keeps running. This resets the description and the handle.

Parameters

  • service - Pointer to an initialized service

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if service is NULL
  • RCL_RET_NOT_INIT if not initialized

◆ rcl_service_get_default_options()

struct rcl_service_options_t rcl_service_get_default_options ( void  )

Get a zero-initialised [rcl_service_options_t] (sched_context = 0).

◆ rcl_service_get_service_name()

const char * rcl_service_get_service_name ( const struct rcl_service_t *  service)

Get the service name.

Parameters

  • service - Pointer to a service

Returns

  • Pointer to service name (null-terminated), or NULL if the handle is not usable (see rcl_service_t::is_usable) or NULL

◆ rcl_service_is_valid()

bool rcl_service_is_valid ( const struct rcl_service_t *  service)

Is this service handle usable?

rcl's rcl_service_is_valid, whose contract is "true for any handle that can be used" — the ported idiom is a guard. See rcl_service_t::is_usable for which states those are.

Parameters

  • service - Pointer to a service

Returns

  • true if usable, false if finalised, uninitialised or NULL

◆ rcl_set_ros_time_override()

rcl_ret_t rcl_set_ros_time_override ( const struct rcl_clock_t *  clock,
int64_t  nanoseconds 
)

Set the time a RCL_ROS_TIME clock reads, in nanoseconds since the epoch — the entry point a /clock subscriber or a bag player calls.

Mirrors rcl_set_ros_time_override, with the one model difference stated at the top of this section: setting a value also ENABLES the override, and a NEGATIVE nanoseconds is RCL_RET_INVALID_ARGUMENT because a negative value is the "no override" sentinel.

◆ rcl_subscription_fini()

rcl_ret_t rcl_subscription_fini ( struct rcl_subscription_t *  subscription,
struct rcl_node_t *  node 
)

Finalize a subscription.

The subscriber is the executor arena's: remove it with rclc_executor_remove_subscription first if it was added. This resets the description and the handle.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if subscription is NULL
  • RCL_RET_NOT_INIT if it is in no finalisable state finalised — the teardown order was wrong, and nothing is dropped. Stated here because of issue 1386: that issue is three sites documenting a stale-node verdict they could not produce, and the same sweep found this one producing it without saying so.

Safety

  • subscription must be a valid pointer

◆ rcl_subscription_get_default_options()

struct rcl_subscription_options_t rcl_subscription_get_default_options ( void  )

Get a zero-initialised [rcl_subscription_options_t].

All fields default to "inherit"/"off": sched_context = 0 (executor default), message_info = 0 (reserved, off). Callers populate only the fields they want before passing the struct to [rclc_subscription_init_with_options].

◆ rcl_subscription_get_topic_name()

const char * rcl_subscription_get_topic_name ( const struct rcl_subscription_t *  subscription)

Get the topic name of a subscription.

Parameters

  • subscription - Pointer to a subscription

Returns

  • Pointer to topic name (null-terminated), or NULL if the handle is not usable (see rcl_subscription_t::is_usable) or NULL

◆ rcl_subscription_is_valid()

bool rcl_subscription_is_valid ( const struct rcl_subscription_t *  subscription)

Is this subscription handle usable?

rcl's rcl_subscription_is_valid, whose contract is "true for any handle that can be used" — the ported idiom is a guard. See rcl_subscription_t::is_usable for which states those are.

Parameters

  • subscription - Pointer to a subscription

Returns

  • true if usable, false if finalised, uninitialised or NULL

◆ rcl_timer_cancel()

rcl_ret_t rcl_timer_cancel ( struct rcl_timer_t *  timer)

Cancel a timer.

A canceled timer will not fire, but can be reset to start again. If registered with an executor, forwards to the executor's cancel_timer.

Parameters

  • timer - Pointer to an initialized timer

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if timer is NULL
  • RCL_RET_NOT_INIT if not initialized

◆ rcl_timer_exchange_period()

rcl_ret_t rcl_timer_exchange_period ( const struct rcl_timer_t *  timer,
int64_t  new_period,
int64_t *  old_period 
)

Swap this timer's period, reporting the one it had. Nanoseconds.

rcl's rcl_timer_exchange_period(const rcl_timer_t *, int64_t new_period, int64_t *old_period), at rcl's arity and in rcl's order. Gap c:timer_exchange_period recorded that a node whose rate is a parameter had to destroy and recreate its timer, because neither C nor Rust could change one in place.

Writes BOTH copies of the period, which is the whole reason this is not a one-line setter:

  • the arena's TimerHeader::period_us, when the timer is registered — the number arena::timer_try_process compares elapsed_us against, so this is the period the dispatcher will honour on its next pass;
  • rcl_timer_t::period_ns always — the registration INPUT rclc_executor_add_timer re-reads, and what rclc_timer_get_period returns. Leaving it stale would make the getter disagree with the dispatcher, which is the "compiles and differs" RFC-0089 exists to stop.

**old_period is the exact nanosecond value last supplied**, not the microsecond-quantised one the arena holds: the struct's copy is written unquantised by rclc_timer_init_with_context and by this function, so a caller reading back what it wrote gets what it wrote. The DISPATCHER's resolution is still microseconds (issue #505), so a period below 1 µs schedules as 0 — the same quantisation rcl_timer_init has always applied, surfaced here rather than introduced.

The elapsed count is NOT rewound, which is rcl's behaviour: upstream exchanges the period and touches nothing else. A timer shortened below its accumulated elapsed time is ready immediately; one lengthened past it waits longer. Call rcl_timer_reset after if the new period should start fresh.

Why <tt>const</tt> on a function that writes

rcl's signature is const rcl_timer_t * and it mutates through timer->impl, so a ported call site passes a handle it holds by value and expects the write. Ours has no impl indirection, so the write is through a cast. That is sound for every reachable timer: rcl_timer_init takes struct rcl_timer_t *, so no timer that was ever initialised is a const-defined object. Taking a non-const parameter instead would have been a silent divergence for exactly the ported callers that hold a const rcl_timer_t *, and C reports that as a warning.

Returns

  • RCL_RET_OK with *old_period written and the new period in force
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL, or new_period is not positive — rcl_timer_init refuses a zero period, and a setter that accepted one would leave the timer in a state its own constructor forbids
  • RCL_RET_NOT_INIT if the timer is uninitialised or finalised, or is registered with an executor that no longer knows the handle

Safety

  • timer must be NULL or point to a valid, non-const-defined rcl_timer_t.
  • old_period must be NULL or writable.

◆ rcl_timer_fini()

rcl_ret_t rcl_timer_fini ( struct rcl_timer_t *  timer)

Finalize a timer.

IDEMPOTENT, per rcl/timer.h verbatim: "A timer that is already invalid (zero initialized) or `NULL` will not fail." Both of the codes this used to return on those paths — RCL_RET_INVALID_ARGUMENT for NULL, RCL_RET_NOT_INIT for a second fini — are values upstream promises never to produce, and RCL_WARN_UNUSED asks the caller to check, so a ported cleanup reported a shutdown failure that had not happened (phase-417 stage 3, ledger row c:timer_fini). Nothing about a fixed arena forbids accepting the call: there is no allocation to release and the release is already idempotent.

Parameters

  • timer - Pointer to a timer, or NULL

Returns

  • RCL_RET_OK — always. A NULL timer and an already-finalised one are successes with nothing to do, not errors.

◆ rcl_timer_get_next_call_time()

rcl_ret_t rcl_timer_get_next_call_time ( const struct rcl_timer_t *  timer,
int64_t *  next_call_time 
)

When this timer next fires, as a point on the clock it is scheduled against.

rcl's rcl_timer_get_next_call_time(const rcl_timer_t *, int64_t *). Gap c:timer_get_next_call_time recorded C as lacking it; the row's why said "Rust has it (`Timer::time_until_next_call`)", which named the RELATIVE sibling — upstream ships both, and rcl_timer_get_time_until_next_call (phase-417 stage 3) is the relative one. This is the absolute one, and it is now + remaining over the SAME derivation, so the pair cannot disagree.

Which clock "now" is read from

The timer's own, which is the property that makes the answer comparable with anything else the caller timestamps:

  • a timer created by rclc_timer_init_on_clock carries an rcl_clock_t *, and that clock is read — so a RCL_ROS_TIME timer answers on /clock's timeline and stops advancing when the playback does, exactly as its dispatch does;
  • a timer created by rcl_timer_init is the WALL timer (rclcpp's create_wall_timer) and carries no clock handle. Its answer is on the platform STEADY clock — the same monotonic source whose spin deltas advance the arena's elapsed_us, so it is the timeline the timer is actually scheduled on rather than a wall-clock approximation of it.

Divergence from rcl, inherited from the sibling accessors: the arena's timer accounting is MICROSECOND-based (issue #505), so the remaining half of this sum has microsecond resolution. The clock read does not.

RCL_RET_TIMER_INVALID and RCL_RET_TIMER_CANCELED have no counterpart in rcl_ret_t (<rclc/detail/rcl_compat.h> declines to map them), so those and "not registered with an executor" all arrive as RCL_RET_NOT_INIT.

Returns

  • RCL_RET_OK with *next_call_time written
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the timer is uninitialised, finalised, or not registered with an executor — nothing is advancing its clock, so it has no next call rather than a next call of zero
  • whatever rclc_clock_get_now_ns reports for a timer whose attached clock is not readable

Safety

  • timer must be NULL or point to a valid rcl_timer_t.
  • next_call_time must be NULL or writable.
  • A non-NULL timer->clock must still point to a live rcl_clock_t.

◆ rcl_timer_get_time_since_last_call()

rcl_ret_t rcl_timer_get_time_since_last_call ( const struct rcl_timer_t *  timer,
int64_t *  time_since_last_call_ns 
)

Nanoseconds accumulated since this timer last fired.

rcl's rcl_timer_get_time_since_last_call(timer, int64_t *). Gap c:timer_get_time_since_last_call records that Rust had it and C did not.

Forwards to Executor::timer_elapsed_us, the arena's elapsed_us counter. This is why the accessor could not read rcl_timer_t and had to reach the executor: rcl_timer_t::last_call_time_ns was written by rclc_timer_init_with_context and rcl_timer_reset and by nothing else — no dispatch path updated it — so a struct-local computation answered 0 for every timer that had ever fired. phase-487 W3 removed the field.

Divergence from rcl, inherited: the executor's timer accounting is MICROSECOND-based (issue #505), so the nanosecond value this reports is a microsecond quantity scaled by 1000, not a nanosecond measurement. The unit and the int64_t out-type are rcl's; the resolution is ours.

Returns

  • RCL_RET_OK with *time_since_last_call_ns written
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the timer is uninitialised, finalised, or not registered with an executor — nothing has been advancing its clock, so there is no elapsed time rather than an elapsed time of zero

Safety

  • timer must be NULL or point to a valid rcl_timer_t.
  • time_since_last_call_ns must be NULL or writable.

◆ rcl_timer_get_time_until_next_call()

rcl_ret_t rcl_timer_get_time_until_next_call ( const struct rcl_timer_t *  timer,
int64_t *  time_until_next_call_ns 
)

Nanoseconds until this timer next fires — NEGATIVE if it is overdue.

rcl's rcl_timer_get_time_until_next_call(timer, int64_t *), marked RCL_WARN_UNUSED. phase-417 stage 3 (ledger row c:timer_get_time_until_next_call) and issue 1049 are the same defect seen from two sides, and the old shape — uint64_t f(timer, uint64_t now) — lost three things at once:

  • the ERROR CHANNEL. The doc comment said the result was "0 if ready now or invalid", so ready-now, NULL, uninitialised, finalised and unregistered were one value and a caller could not tell a due timer from a dead one.
  • OVERDUE. rcl's header: "a negative value indicates the timer call is overdue by that amount". Unsigned cannot express it, so lateness read as 0 — which is also what "fires now" reads as.
  • the SOURCE OF TRUTH. It computed from rcl_timer_t::last_call_time_ns (removed by phase-487 W3), which rclc_timer_init_with_context and rcl_timer_reset wrote and no dispatch path ever updated, so for any timer the executor was actually running the answer was permanently 0 (issue 1049). It forwards to the arena now, the same way W5.c's [rcl_timer_get_time_since_last_call] and [rcl_timer_is_ready] do, and the caller-supplied "now" is gone with it — a second time base is what let the two drift apart.

Divergence from rcl, inherited from the sibling accessors: the arena's timer accounting is MICROSECOND-based (issue #505), so this nanosecond value is a microsecond quantity scaled by 1000. The unit is rcl's; the resolution is ours.

RCL_RET_TIMER_INVALID and RCL_RET_TIMER_CANCELED have no counterpart in rcl_ret_t and <rclc/detail/rcl_compat.h> deliberately does not map them, so the four rcl outcomes reach a caller as three: those two and "not registered" all arrive as RCL_RET_NOT_INIT.

Returns

  • RCL_RET_OK with *time_until_next_call_ns written
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the timer is uninitialised, finalised, or not registered with an executor — nothing is advancing its clock, so it has no time until its next call rather than a time of zero

Safety

  • timer must be NULL or point to a valid rcl_timer_t.
  • time_until_next_call_ns must be NULL or writable.

◆ rcl_timer_is_canceled()

rcl_ret_t rcl_timer_is_canceled ( const struct rcl_timer_t *  timer,
bool *  is_canceled 
)

Has this timer been cancelled?

rcl's rcl_timer_is_canceled(timer, bool *). Gap c:timer_is_canceled records that our C timer had no cancel predicate under any spelling while C++ and Rust both did.

Forwards to Executor::timer_is_canceled for a registered timer — the arena flag arena::timer_try_process actually consults, and the one rcl_timer_cancel sets through Executor::cancel_timer. A timer that has been initialised but not yet added to an executor has no arena entry, so its own rclc_timer_state_t is the whole truth and is read instead.

Returns

  • RCL_RET_OK with *is_canceled written
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the timer is uninitialised or finalised

Safety

  • timer must be NULL or point to a valid rcl_timer_t.
  • is_canceled must be NULL or writable.

◆ rcl_timer_is_ready()

rcl_ret_t rcl_timer_is_ready ( const struct rcl_timer_t *  timer,
bool *  is_ready 
)

Would this timer fire on the next nros_executor_spin_* pass?

rcl's rcl_timer_is_ready(timer, bool *). Gap c:timer_is_ready records that Rust had the predicate and C did not.

Forwards to Executor::timer_is_ready, which evaluates arena::timer_try_process's own guard against the arena entry — cancelled is never ready, a fired one-shot is never ready again, otherwise elapsed >= period. Deliberately not re-derived here: a readiness answer that can disagree with the dispatcher is worse than no answer.

Returns

  • RCL_RET_OK with *is_ready written
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the timer is uninitialised, finalised, or not registered with an executor — an unregistered timer is dispatched by nobody, so it has no readiness rather than a readiness of false

Safety

  • timer must be NULL or point to a valid rcl_timer_t.
  • is_ready must be NULL or writable.

◆ rcl_timer_reset()

rcl_ret_t rcl_timer_reset ( struct rcl_timer_t *  timer)

Reset a timer.

This resets the timer's last call time and starts it running again if it was canceled. If registered with an executor, forwards to the executor's reset_timer.

Parameters

  • timer - Pointer to an initialized timer

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if timer is NULL
  • RCL_RET_NOT_INIT if not initialized

◆ rcl_trigger_guard_condition()

rcl_ret_t rcl_trigger_guard_condition ( struct rcl_guard_condition_t *  guard)

rcl's spelling of [rclc_guard_condition_trigger], forwarding to it.

Kept, not retired: rcl HAS this name, and RFC-0089's alias rule makes a name upstream has load-bearing rather than a courtesy — a ported rcl node writes rcl_trigger_guard_condition(&gc) and must keep compiling. It is not deprecated for the same reason.

Safety

See [rclc_guard_condition_trigger].

◆ rclc_action_abort()

rcl_ret_t rclc_action_abort ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal,
const uint8_t *  result,
size_t  result_len 
)

Mark a goal as aborted with an optional result.

Delegates to ActionServerRawHandle::complete_goal_raw.

◆ rclc_action_cancel_goal()

rcl_ret_t rclc_action_cancel_goal ( struct rcl_action_client_t *  client,
const struct rclc_goal_uuid_t *  goal_uuid 
)

Request cancellation of a goal.

◆ rclc_action_canceled()

rcl_ret_t rclc_action_canceled ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal,
const uint8_t *  result,
size_t  result_len 
)

Mark a goal as canceled with an optional result.

Delegates to ActionServerRawHandle::complete_goal_raw.

◆ rclc_action_client_action_server_is_ready()

bool rclc_action_client_action_server_is_ready ( const struct rcl_action_client_t *  client,
struct rclc_executor_t *  executor 
)

Non-blocking snapshot of action-server visibility. Mirrors rclcpp_action::Client::action_server_is_ready. Takes executor for the same reason as [rclc_action_client_wait_for_action_server].

◆ rclc_action_client_poll()

rcl_ret_t rclc_action_client_poll ( struct rcl_action_client_t *  client)

Poll the action client for pending async replies (non-blocking).

Note: In the unified design (77.6+), rclc_executor_spin_some already dispatches action_client_raw_try_process which invokes callbacks. This function is provided for manual polling outside the executor loop.

Safety

client must be a valid pointer.

◆ rclc_action_client_set_feedback_callback()

rcl_ret_t rclc_action_client_set_feedback_callback ( struct rcl_action_client_t *  client,
rclc_feedback_callback_t  callback,
void *  context 
)

Set feedback callback.

◆ rclc_action_client_set_goal_response_callback()

rcl_ret_t rclc_action_client_set_goal_response_callback ( struct rcl_action_client_t *  client,
rclc_goal_response_callback_t  callback,
void *  context 
)

Set the goal response callback for async goal sending.

Called during rclc_executor_spin_some when the server accepts or rejects a goal sent via rclc_action_send_goal_async.

Safety

client must be valid.

◆ rclc_action_client_set_result_callback()

rcl_ret_t rclc_action_client_set_result_callback ( struct rcl_action_client_t *  client,
rclc_result_callback_t  callback,
void *  context 
)

Set result callback.

◆ rclc_action_client_wait_for_action_server()

rcl_ret_t rclc_action_client_wait_for_action_server ( struct rcl_action_client_t *  client,
struct rclc_executor_t *  executor,
uint32_t  timeout_ms 
)

Block until the action server's send-goal queryable is discoverable on the network, or timeout_ms elapses.

Mirrors rclcpp_action::Client::wait_for_action_server and the underlying ActionClient::wait_for_action_server. Spins on the action's send_goal service client's readiness (the goal queryable is the load-bearing entity for the first rclc_action_send_goal call) via the same primitive as rclc_client_wait_for_service (phase-428 W13).

Returns

  • RCL_RET_OK — server visible.
  • RCL_RET_TIMEOUT — timeout_ms elapsed without seeing a token.
  • RCL_RET_UNSUPPORTED — the backend cannot know whether a server is up (XRCE: the Agent owns the DDS graph), returned at once rather than after the budget, because no answer can arrive (issue 1686). A caller that may send blind proceeds; the goal request's own timeout is then the probe.
  • RCL_RET_NOT_INIT — client not registered with an executor.
  • RCL_RET_ERROR — transport-level failure.

◆ rclc_action_execute()

rcl_ret_t rclc_action_execute ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal 
)

Execute a goal (transition to Executing).

Idempotent: delegates to ActionServerRawHandle::set_goal_status which is a no-op if the goal isn't in the active-goals vector. Returns RCL_RET_OK on success, RCL_RET_NOT_INIT if the server isn't registered.

◆ rclc_action_expire_goals()

rcl_ret_t rclc_action_expire_goals ( struct rcl_action_server_t *  server,
size_t *  num_expired 
)

Eagerly reclaim every completed result whose get_result reply has already been sent, and report how many were reclaimed.

rcl's rcl_action_expire_goals — phase-417 W4.b, ledger row c:action_expire_goals. ADOPT-BOUNDED, and the envelope is the whole point of the row: upstream's trigger is a CLOCK (a goal expires result_timeout after it terminates, 15 min by default) and it fills a caller-supplied rcl_action_goal_info_t array with the goals that went. Neither half survives here:

  • No timeout. ActionServerCore is no_std with no time source threaded through it (RFC-0036), so there is nothing to measure a result_timeout against. The trigger is the CALLER, and reclamation otherwise happens on demand when a completion needs slab room — which is what already bounds the memory upstream's timer exists to bound.
  • No expired_goals report. An entry is reclaimed the moment its result has been delivered, so "which goals expired" is a question about a clock we do not have; the count is what remains true.

Calling this is OPTIONAL. It exists for a server that would rather return the slab eagerly (before a long idle period, say) than at the next completion.

Parameters

  • server - Pointer to an action server
  • num_expired - Receives the number of results reclaimed (may be 0)

Returns

  • RCL_RET_OK — *num_expired holds the count, which may legitimately be 0.
  • RCL_RET_INVALID_ARGUMENT — server or num_expired is NULL.
  • RCL_RET_NOT_INIT — the server is UNINITIALIZED or SHUTDOWN, was never registered with an executor.

*num_expired is left untouched on every error path, for the same reason [rclc_action_server_get_active_goal_count] leaves its own out-parameter alone.

◆ rclc_action_get_goal_status()

rcl_ret_t rclc_action_get_goal_status ( const struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal,
enum rclc_goal_status_t *  status 
)

Look up a goal's current status in the arena by UUID.

Returns RCL_RET_OK and writes the arena-sourced status on success. Returns RCLC_RET_NOT_FOUND if the arena has already retired the goal (completed + result delivered, or cancelled + acknowledged).

This is the authoritative successor to the removed goal->status field: lifecycle transitions are driven by ActionServerArenaEntry::active_goals and read back through this function.

◆ rclc_action_get_result()

rcl_ret_t rclc_action_get_result ( struct rcl_action_client_t *  client,
struct rclc_executor_t *  executor,
const struct rclc_goal_uuid_t *  goal_uuid,
enum rclc_goal_status_t *  status,
uint8_t *  result,
size_t  result_capacity,
size_t *  result_len 
)

Request result of a goal (blocking convenience).

Calls rclc_action_get_result_async then spins the executor until the result arrives or timeout. Never calls zpico_get directly.

◆ rclc_action_get_result_async()

rcl_ret_t rclc_action_get_result_async ( struct rcl_action_client_t *  client,
const struct rclc_goal_uuid_t *  goal_uuid 
)

Request a goal result asynchronously (non-blocking).

Sends the get_result request and returns immediately. The result arrives via the result_callback registered with rclc_action_client_set_result_callback, invoked during rclc_executor_spin_some.

Safety

All pointers must be valid.

◆ rclc_action_publish_feedback_raw()

rcl_ret_t rclc_action_publish_feedback_raw ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal,
const uint8_t *  feedback,
size_t  feedback_len 
)

Publish feedback for an active goal.

Delegates to ActionServerRawHandle::publish_feedback_raw; the arena enforces goal liveness and is the sole source of truth for lifecycle state.

◆ rclc_action_send_goal()

rcl_ret_t rclc_action_send_goal ( struct rcl_action_client_t *  client,
struct rclc_executor_t *  executor,
const uint8_t *  goal,
size_t  goal_len,
struct rclc_goal_uuid_t *  goal_uuid 
)

Send a goal request. Send a goal (blocking convenience).

Calls rclc_action_send_goal_async then spins the executor until the goal is accepted/rejected or timeout. Never calls zpico_get directly — all I/O is driven by the executor's spin_once.

Like the runtime's Promise::wait, this is syntactic sugar over async + spin.

Returns

Three outcomes, three codes — they were two before issue 0868 (see the C++ twin nros_cpp_action_client_send_goal):

  • RCL_RET_OK — the server ACCEPTED; goal_uuid is filled.
  • RCLC_RET_REJECTED — the server RECEIVED the goal and declined it.
  • RCL_RET_TIMEOUT — no goal response within the blocking budget. The server may never have received the goal at all.
  • RCL_RET_ERROR — the goal could not be SENT.
  • RCLC_RET_REENTRANT — called from inside a dispatch callback.

◆ rclc_action_send_goal_async()

rcl_ret_t rclc_action_send_goal_async ( struct rcl_action_client_t *  client,
const uint8_t *  goal,
size_t  goal_len,
struct rclc_goal_uuid_t *  goal_uuid 
)

Send a goal asynchronously (non-blocking).

Sends the goal request and returns immediately. The goal response (accepted/rejected) arrives via the goal_response_callback registered with rclc_action_client_set_goal_response_callback, invoked during rclc_executor_spin_some.

The goal_uuid output is filled with the generated goal UUID on success.

Safety

All pointers must be valid. goal must point to goal_len bytes of CDR-serialized goal data (with CDR header).

◆ rclc_action_server_get_active_goal_count()

rcl_ret_t rclc_action_server_get_active_goal_count ( struct rcl_action_server_t *  server,
size_t *  out 
)

Get the number of currently active goals.

Phase-379 W6 decision 3: ONE function in rcl's shape, serving both tiers. Upstream ships no count function; its nearest neighbour is rcl_action_server_get_goal_handles(server, ***handles, size_t *num_goals) -> rcl_ret_t, which reports the count through an out-param and keeps the return code for "did the query work". This replaces the pair rclc_action_server_get_active_goal_count(server) -> size_t (answered 0 on every error) and nros_action_server_active_goal_count_raw(server) -> int32_t (negative = error code), each of which collapsed the two channels into one value.

Reads the executor arena through ActionServerRawHandle::active_goal_count. A polled server, whose ActionServerCore is inline, answers through [rclc_polling_action_server_get_active_goal_count]; until phase-487 W4 both tiers shared this entry point and were told apart by state.

Returns:

  • RCL_RET_OK — *out holds the count, which may legitimately be 0.
  • RCL_RET_INVALID_ARGUMENT — server or out is NULL.
  • RCL_RET_NOT_INIT — the server is UNINITIALIZED or SHUTDOWN; or it is INITIALIZED but was never registered with an executor (or has been finalised).

*out is left untouched on every error path, so a caller that ignores the return code reads back its own initialiser rather than a fabricated 0 — which is precisely the ambiguity the old size_t spelling could not escape.

◆ rclc_action_server_goal_exists()

bool rclc_action_server_goal_exists ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal 
)

Is goal a goal this server still knows about?

rcl's rcl_action_server_goal_exists over OUR goal handle, hence the distinct rclc_ name (phase-492 W1.b) — phase-417 W4.b, ledger row c:action_server_goal_exists. TRUE while the goal is ACTIVE and while its completed result is still retained for a later get_result, which is rcl's own window (its goal-handle table keeps a terminated goal until rcl_action_expire_goals reclaims it).

**This is not what [rclc_action_get_goal_status] answers**, and the row was open on the guess that it was. That lookup reads the ACTIVE set only, so it returns RCLC_RET_NOT_FOUND for a goal that has completed and whose result is still sitting in the slab — i.e. for exactly the goals a client is in the middle of fetching. A ported if (rclc_action_server_goal_exists (...)) guard written against that mapping would have been wrong in the one window it matters.

Parameters

  • server - Pointer to an action server
  • goal - The goal handle (its 16-byte UUID is the key)

Returns

  • true if the server knows the goal; false for a NULL argument, an uninitialised/finalised server, or an unknown goal. A predicate, so there is no separate error channel — the ported idiom is a guard, the same shape as rcl_service_is_valid.

◆ rclc_action_server_init_with_callbacks()

rcl_ret_t rclc_action_server_init_with_callbacks ( struct rcl_action_server_t *  server,
const struct rcl_node_t *  node,
const char *  action_name,
const struct rclc_action_type_t *  type_info,
rclc_goal_callback_t  goal_callback,
rclc_cancel_callback_t  cancel_callback,
rclc_accepted_callback_t  accepted_callback,
void *  context 
)

Initialize an action server.

Stores metadata (name, type, callbacks). RMW entity creation is deferred to rclc_executor_attach_action_server().

◆ rclc_action_server_init_with_options()

rcl_ret_t rclc_action_server_init_with_options ( struct rcl_action_server_t *  server,
const struct rcl_node_t *  node,
const char *  action_name,
const struct rclc_action_type_t *  type_info,
rclc_goal_callback_t  goal_callback,
rclc_cancel_callback_t  cancel_callback,
rclc_accepted_callback_t  accepted_callback,
void *  context,
const struct rclc_qos_t *  qos,
const struct rcl_action_server_options_t *  options 
)

Phase 189.M3.3.b — initialize an action server with custom QoS + named options. Like [rclc_action_server_init_with_qos] except a non-zero options->sched_context is stashed so rclc_executor_attach_action_server binds the resulting executor handle to that scheduling context once known.

Safety

All non-NULL pointers must be valid + the node initialized; qos / options may be NULL.

◆ rclc_action_server_init_with_qos()

rcl_ret_t rclc_action_server_init_with_qos ( struct rcl_action_server_t *  server,
const struct rcl_node_t *  node,
const char *  action_name,
const struct rclc_action_type_t *  type_info,
rclc_goal_callback_t  goal_callback,
rclc_cancel_callback_t  cancel_callback,
rclc_accepted_callback_t  accepted_callback,
void *  context,
const struct rclc_qos_t *  qos 
)

Phase 193.4b — initialize an action server with an explicit QoS profile (rclc's _with_options). The profile applies to the three underlying service servers (send_goal / cancel_goal / get_result); the feedback + status publishers keep their own profiles. qos NULL ⇒ the services default. Same as [rclc_action_server_init_with_callbacks] otherwise.

Safety

All non-NULL pointers must be valid + the node initialized.

◆ rclc_action_succeed()

rcl_ret_t rclc_action_succeed ( struct rcl_action_server_t *  server,
const struct rclc_goal_handle_t *  goal,
const uint8_t *  result,
size_t  result_len 
)

Mark a goal as succeeded with a result.

Delegates to ActionServerRawHandle::complete_goal_raw; the arena owns the active-goals vector and retires the goal there.

◆ rclc_action_try_recv_feedback()

rcl_ret_t rclc_action_try_recv_feedback ( struct rcl_action_client_t *  client)

Try to receive feedback for an active goal (non-blocking).

If feedback is available, invokes the feedback callback (if set). Returns RCL_RET_OK if feedback was received and dispatched, RCL_RET_TIMEOUT if no feedback is available.

◆ rclc_cdr_align()

int32_t rclc_cdr_align ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
size_t  alignment 
)

Advance the cursor to the next alignment-byte boundary of the CDR STREAM (relative to origin, never to the buffer pointer), consuming the padding the writer emitted. This is [CdrReader::align] behind the C ABI, so it carries the same edition rule (XCDR2 caps 8-byte primitives at 4) and the header-only readers in <rclc/detail/view.h> agree with the Rust reader byte for byte instead of re-deriving the arithmetic (issue 1148).

Returns 0 on success, -1 if alignment is 0 or the padding would run past end.

◆ rclc_cdr_begin_dheader()

int64_t rclc_cdr_begin_dheader ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin 
)

Begin a DHEADER-delimited struct. Under XCDR2 (iron/jazzy+) reserves a 4-byte DHEADER at the cursor (aligned) and advances it, returning the mark (its byte offset). Under XCDR1 (humble) this is a NO-OP returning -1. The generated C _serialize_inline calls this at the top of every struct and passes the mark to [rclc_cdr_end_dheader]. Returns -2 on any bounds/pointer failure.

Safety

ptr/end/origin follow the same (cursor, end, origin) contract as the write helpers.

◆ rclc_cdr_begin_dheader_read()

int64_t rclc_cdr_begin_dheader_read ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin 
)

Begin reading a DHEADER-delimited struct. Under XCDR2 reads the 4-byte DHEADER at the cursor (advancing it) and returns the struct's END offset; under XCDR1 returns -1 (no-op). Returns -2 on failure. The generated C _deserialize passes the result to [rclc_cdr_end_dheader_read].

Safety

Same (cursor, end, origin) contract as the read helpers.

◆ rclc_cdr_end_dheader()

int32_t rclc_cdr_end_dheader ( int64_t  mark,
uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin 
)

Finish a DHEADER-delimited struct: backpatch the reserved slot (from [rclc_cdr_begin_dheader]) with the bytes written since. mark < 0 (XCDR1) is a no-op. Returns 0 on success, -1 on failure.

Safety

Same buffer contract as the write helpers.

◆ rclc_cdr_end_dheader_read()

int32_t rclc_cdr_end_dheader_read ( int64_t  scope,
const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin 
)

Finish reading a DHEADER-delimited struct: skip any unknown trailing members by advancing the cursor to the struct END (scope from [rclc_cdr_begin_dheader_read]). scope < 0 (XCDR1) is a no-op. Returns 0 on success, -1 if the reader over-read past the declared end.

Safety

Same buffer contract as the read helpers.

◆ rclc_cdr_read_bool()

int32_t rclc_cdr_read_bool ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
bool *  value 
)

Read a CDR-encoded bool (1 byte) into *value and advance the cursor.

Returns 0 on success, -1 if the cursor would overrun end, the payload is malformed, or any pointer is null.

◆ rclc_cdr_read_f32()

int32_t rclc_cdr_read_f32 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
float *  value 
)

Read a CDR-encoded IEEE-754 float into *value.

◆ rclc_cdr_read_f64()

int32_t rclc_cdr_read_f64 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
double *  value 
)

Read a CDR-encoded IEEE-754 double into *value.

◆ rclc_cdr_read_i16()

int32_t rclc_cdr_read_i16 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int16_t *  value 
)

Read a CDR-encoded int16_t into *value.

◆ rclc_cdr_read_i32()

int32_t rclc_cdr_read_i32 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int32_t *  value 
)

Read a CDR-encoded int32_t into *value.

◆ rclc_cdr_read_i64()

int32_t rclc_cdr_read_i64 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int64_t *  value 
)

Read a CDR-encoded int64_t into *value.

◆ rclc_cdr_read_i8()

int32_t rclc_cdr_read_i8 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int8_t *  value 
)

Read a CDR-encoded int8_t into *value and advance the cursor.

◆ rclc_cdr_read_string()

int32_t rclc_cdr_read_string ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
char *  value,
size_t  max_len 
)

Read a CDR string into a fixed-size C buffer. Fails if the encoded length exceeds max_len. Always null-terminates the output on success.

◆ rclc_cdr_read_u16()

int32_t rclc_cdr_read_u16 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint16_t *  value 
)

Read a CDR-encoded uint16_t (2-byte aligned) into *value.

◆ rclc_cdr_read_u32()

int32_t rclc_cdr_read_u32 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint32_t *  value 
)

Read a CDR-encoded uint32_t (4-byte aligned) into *value.

◆ rclc_cdr_read_u64()

int32_t rclc_cdr_read_u64 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint64_t *  value 
)

Read a CDR-encoded uint64_t (8-byte aligned) into *value.

◆ rclc_cdr_read_u8()

int32_t rclc_cdr_read_u8 ( const uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint8_t *  value 
)

Read a CDR-encoded uint8_t into *value and advance the cursor. See [rclc_cdr_read_bool] for the buffer contract.

◆ rclc_cdr_write_bool()

int32_t rclc_cdr_write_bool ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
bool  value 
)

Write a CDR-encoded bool (1 byte) and advance the cursor.

Returns 0 on success, -1 if the cursor would overrun end or any pointer is null.

◆ rclc_cdr_write_encaps_header()

int32_t rclc_cdr_write_encaps_header ( uint8_t **  ptr,
const uint8_t *  end 
)

Write the 4-byte CDR encapsulation header for the active ROS edition and advance the cursor: XCDR1 00 01 00 00 (humble) or XCDR2 DELIMITED_CDR2 00 09 00 00 (iron/jazzy+). Replaces the hardcoded header the generated C _serialize used to emit. Returns 0 on success, -1 on overrun/null.

Safety

ptr is a *mut *mut u8 cursor; end bounds the buffer.

◆ rclc_cdr_write_f32()

int32_t rclc_cdr_write_f32 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
float  value 
)

Write a CDR-encoded IEEE-754 float (4-byte aligned) and advance the cursor.

◆ rclc_cdr_write_f64()

int32_t rclc_cdr_write_f64 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
double  value 
)

Write a CDR-encoded IEEE-754 double (8-byte aligned) and advance the cursor.

◆ rclc_cdr_write_i16()

int32_t rclc_cdr_write_i16 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int16_t  value 
)

Write a CDR-encoded int16_t and advance the cursor.

◆ rclc_cdr_write_i32()

int32_t rclc_cdr_write_i32 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int32_t  value 
)

Write a CDR-encoded int32_t and advance the cursor.

◆ rclc_cdr_write_i64()

int32_t rclc_cdr_write_i64 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int64_t  value 
)

Write a CDR-encoded int64_t and advance the cursor.

◆ rclc_cdr_write_i8()

int32_t rclc_cdr_write_i8 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
int8_t  value 
)

Write a CDR-encoded int8_t and advance the cursor.

◆ rclc_cdr_write_string()

int32_t rclc_cdr_write_string ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
const char *  value 
)

Write a null-terminated string (CDR: u32 length inc. null + bytes + null).

◆ rclc_cdr_write_string_n()

int32_t rclc_cdr_write_string_n ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
const char *  data,
size_t  data_len 
)

Write a ptr+len string (CDR: u32 length inc. null + bytes + null).

◆ rclc_cdr_write_u16()

int32_t rclc_cdr_write_u16 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint16_t  value 
)

Write a CDR-encoded uint16_t (2 bytes, little-endian, 2-byte aligned) and advance the cursor.

◆ rclc_cdr_write_u32()

int32_t rclc_cdr_write_u32 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint32_t  value 
)

Write a CDR-encoded uint32_t (4 bytes, little-endian, 4-byte aligned) and advance the cursor.

◆ rclc_cdr_write_u64()

int32_t rclc_cdr_write_u64 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint64_t  value 
)

Write a CDR-encoded uint64_t (8 bytes, little-endian, 8-byte aligned) and advance the cursor.

◆ rclc_cdr_write_u8()

int32_t rclc_cdr_write_u8 ( uint8_t **  ptr,
const uint8_t *  end,
const uint8_t *  origin,
uint8_t  value 
)

Write a CDR-encoded uint8_t and advance the cursor. See [rclc_cdr_write_bool] for the buffer contract.

◆ rclc_clear_custom_transport()

rcl_ret_t rclc_clear_custom_transport ( void  )

Phase 115.C — clear any previously-registered custom transport. Equivalent to rclc_set_custom_transport(NULL). Convenience for teardown paths.

◆ rclc_client_call()

rcl_ret_t rclc_client_call ( struct rcl_client_t *  client,
const uint8_t *  request_data,
size_t  request_len,
uint8_t *  response_data,
size_t  response_capacity,
size_t *  response_len 
)

Call a service (blocking convenience over the async pair).

Phase 82: signature unchanged, but no longer blocks at the transport layer. Internally calls rclc_client_send_request_async and spins the registered executor via rclc_executor_spin_some until the response arrives or the client's timeout_ms elapses. The client must have been registered with rclc_executor_attach_client.

Parameters

  • client - Pointer to a registered client
  • request_data - CDR-serialized request data
  • request_len - Length of request data
  • response_data - Buffer to receive CDR-serialized response
  • response_capacity - Capacity of response buffer
  • response_len - Output: actual length of response data

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL
  • RCL_RET_NOT_INIT if the client isn't registered with an executor
  • RCL_RET_TIMEOUT if no response within timeout_ms
  • RCL_RET_ERROR on call failure

◆ rclc_client_init_default()

rcl_ret_t rclc_client_init_default ( struct rcl_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name 
)

Initialize a service client (Phase 82: metadata-only).

Stores the service name/type metadata and a ServiceClientInternal blob; the actual transport handle (RmwServiceClient) is created later by rclc_executor_attach_client. This deferred lifecycle matches rclc_service_init_default (server side) and the action client.

rclc's rclc_client_init_default, at rclc's arity. The typesupport argument keeps OUR type: const rclc_service_type_t* where rclc takes a const rosidl_service_type_support_t*, so passing a rosidl typesupport is an incompatible-pointer diagnostic at the call (same reason as rclc_service_init_default: a typesupport's members are its contract). The response callback is supplied at registration (rclc_executor_attach_client*), as rclc's is at rclc_executor_add_client.

Parameters

  • client - Pointer to a zero-initialized client
  • node - Pointer to an initialized node
  • type_info - Pointer to service type information
  • service_name - Service name (null-terminated string)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized

◆ rclc_client_init_with_options()

rcl_ret_t rclc_client_init_with_options ( struct rcl_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name,
const struct rclc_qos_t *  qos,
const struct rcl_client_options_t *  options 
)

Phase 189.M3.3.a — initialize a service client with custom QoS + named options. Like [rclc_client_init_with_qos] except a non-zero options->sched_context is stashed so rclc_executor_attach_client binds the resulting executor handle to that scheduling context once known.

Safety

All non-NULL pointers must be valid + the node initialized; qos / options may be NULL.

◆ rclc_client_init_with_qos()

rcl_ret_t rclc_client_init_with_qos ( struct rcl_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name,
const struct rclc_qos_t *  qos 
)

Phase 193.4b — initialize a service client with an explicit QoS profile (rclc's _with_options; the profile applies to both the request + reply endpoints). qos NULL ⇒ the services default. Same as [rclc_client_init_default] otherwise.

Safety

All non-NULL pointers must be valid + the node initialized.

◆ rclc_client_request_publisher_get_actual_qos()

rcl_ret_t rclc_client_request_publisher_get_actual_qos ( const struct rcl_client_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS the backend GRANTED this client's REQUEST endpoint — the publisher that sends calls.

rcl_client_request_publisher_get_actual_qos. A policy the backend could not report reads back as NROS_QOS_*_UNKNOWN, never as your request — see [rclc_publisher_get_actual_qos](crate::publisher::rclc_publisher_get_actual_qos).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the handle is in no usable state, or is callback-mode and not yet added to an executor — there is no entity to ask, which is a different answer from UNKNOWN ("there is an entity and it cannot say")

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_client_response_subscription_get_actual_qos()

rcl_ret_t rclc_client_response_subscription_get_actual_qos ( const struct rcl_client_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS the backend GRANTED this client's RESPONSE endpoint — the subscription that receives replies.

rcl_client_response_subscription_get_actual_qos. A policy the backend could not report reads back as NROS_QOS_*_UNKNOWN, never as your request — see [rclc_publisher_get_actual_qos](crate::publisher::rclc_publisher_get_actual_qos).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the handle is in no usable state, or is callback-mode and not yet added to an executor — there is no entity to ask, which is a different answer from UNKNOWN ("there is an entity and it cannot say")

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_client_send_request_async()

rcl_ret_t rclc_client_send_request_async ( struct rcl_client_t *  client,
const uint8_t *  request_data,
size_t  request_len 
)

Send a service request asynchronously (Phase 82).

Non-blocking. The reply is delivered via the registered response_callback during rclc_executor_spin_some. The user must have previously registered the client with rclc_executor_attach_client.

Returns

  • RCL_RET_OK on success
  • RCL_RET_NOT_INIT if the client is not registered with an executor
  • RCLC_RET_BAD_SEQUENCE if a previous request is still pending
  • RCL_RET_ERROR on transport failure

◆ rclc_client_server_available()

rcl_ret_t rclc_client_server_available ( struct rcl_client_t *  client,
int32_t *  out 
)

Phase 124.C.3 — synchronous, graph-aware "is the matching server up?" probe. Unlike [rclc_client_wait_for_service] this never spins the executor: it asks the active RMW backend whether at least one matching server has been observed on the RMW graph and returns immediately.

out receives 1 if a server is visible, 0 if none is yet, -1 if the backend cannot answer (e.g. XRCE without participant enumeration). Callers that want the same answer rounded to a hard yes/no should treat -1 as "unknown — assume yes" or use [rclc_client_wait_for_service] instead.

Returns

  • RCL_RET_OK — *out was written (0, 1, or -1).
  • RCL_RET_INVALID_ARGUMENT — client or out is null.
  • RCL_RET_NOT_INIT — client not registered with an executor.
  • RCL_RET_ERROR — transport-level failure.

◆ rclc_client_service_is_ready()

bool rclc_client_service_is_ready ( const struct rcl_client_t *  client)

Non-blocking snapshot of whether a matching service server is currently visible. Mirrors rclcpp::ClientBase::service_is_ready and rcl's rcl_service_server_is_available. Returns false when the client isn't registered with an executor or the backend lacks liveliness discovery (in which case use rclc_client_wait_for_service instead, which handles those cases conservatively).

◆ rclc_client_set_response_callback()

rcl_ret_t rclc_client_set_response_callback ( struct rcl_client_t *  client,
rclc_response_callback_t  callback,
void *  context 
)

Set the response callback fired by rclc_executor_spin_some when an async request has its reply delivered.

phase-487 W2 — the callback and context are written into the client's executor-arena entry, which owns them; the client struct keeps neither. So the client must be ADDED first (rclc_executor_attach_client), and a client removed and re-added starts with no callback. Before W2 the setter wrote the struct and the arena dispatched through a trampoline that read it back, which is the back-reference RFC-0096 D9 removes.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if client is NULL
  • RCL_RET_NOT_INIT if the client is not added to an executor

Safety

client must be a valid pointer; context is passed through untouched.

◆ rclc_client_set_timeout()

rcl_ret_t rclc_client_set_timeout ( struct rcl_client_t *  client,
uint32_t  timeout_ms 
)

Set the default timeout used by rclc_client_call.

◆ rclc_client_take_response()

rcl_ret_t rclc_client_take_response ( struct rcl_client_t *  client,
uint8_t *  response_data,
size_t  response_capacity,
size_t *  response_len 
)

Poll for the reply to the most recently sent async request.

Returns

  • RCL_RET_OK if the reply was filled into response_data
  • RCLC_RET_TRY_AGAIN if no reply yet (caller should spin and retry)
  • RCL_RET_NOT_INIT if the client isn't registered or has no pending request
  • RCL_RET_ERROR on transport failure

◆ rclc_client_wait_for_service()

rcl_ret_t rclc_client_wait_for_service ( struct rcl_client_t *  client,
uint32_t  timeout_ms 
)

Block until a matching service server is discoverable, or timeout_ms elapses. Mirrors rclcpp::ClientBase::wait_for_service and the the underlying Client::wait_for_service.

The client must already have been registered with the executor via rclc_executor_attach_client. A spin on rclc_client_service_is_ready's query: the executor is spun cooperatively between checks, and each check is a synchronous read of the discovery state the backend maintains (on zenoh, the matched-server set fed by liveliness PUT/DELETE — phase-428 W13). Nothing is latched.

Returns

  • RCL_RET_OK — server is visible (proceed with rclc_client_call).
  • RCL_RET_TIMEOUT — timeout_ms elapsed without seeing a token.
  • RCL_RET_UNSUPPORTED — the backend cannot know (XRCE), returned at once: issue 1087 made such a backend wait out the budget and report TIMEOUT, which every client read as "no server" (issue 1686). A caller that may send blind proceeds; the call's own timeout is the probe.
  • RCL_RET_NOT_INIT — client not registered with an executor.
  • RCL_RET_ERROR — transport-level failure.

◆ rclc_clock_get_now_time()

rcl_ret_t rclc_clock_get_now_time ( const struct rcl_clock_t *  clock,
struct rclc_time_t *  time_out 
)

Get the current time from a clock as an rclc_time_t (seconds + nanoseconds). rcl's rcl_clock_get_now writes a nanosecond count; that is [rcl_clock_get_now] here, and this is the struct-valued sibling (phase-492 W1.b — it was the one spelled rcl_clock_get_now, with a different out-type than rcl's).

◆ rclc_clock_get_type()

enum rcl_clock_type_t rclc_clock_get_type ( const struct rcl_clock_t *  clock)

Get the clock type.

◆ rclc_clock_get_zero_initialized()

struct rcl_clock_t rclc_clock_get_zero_initialized ( void  )

Get a zero-initialized clock.

◆ rclc_clock_is_valid()

bool rclc_clock_is_valid ( const struct rcl_clock_t *  clock)

Check if a clock is valid.

◆ rclc_duration_from_nanoseconds()

struct rcl_duration_t rclc_duration_from_nanoseconds ( int64_t  nanoseconds)

Convert nanoseconds to a rcl_duration_t structure.

The duration half of rclc_time_from_nanoseconds, and the same encoding — builtin_interfaces/msg/Duration has the identical {sec, nanosec} shape and the identical [0, 1e9) rule on nanosec. Issue 0799: a negative span is ordinary ("how far ahead of the deadline are we" is negative half the time), and until this existed the C++ Duration::to_msg open-coded the split rather than delegate to a _time_ entry point that got negatives wrong.

◆ rclc_executor_add_on_shutdown_callback()

rcl_ret_t rclc_executor_add_on_shutdown_callback ( struct rclc_executor_t *  executor,
rclc_shutdown_callback_t  callback,
void *  context,
rclc_shutdown_callback_handle_t *  out_handle 
)

Register a callback to run AFTER the executor's session is closed.

Issue 0790 — rclcpp's add_on_shutdown_callback / rclcpp::on_shutdown. The entities are gone by the time it runs, so anything that needs the wire belongs in [rclc_executor_add_pre_shutdown_callback] instead.

Safety

Same contract as [rclc_executor_add_pre_shutdown_callback].

◆ rclc_executor_add_pre_shutdown_callback()

rcl_ret_t rclc_executor_add_pre_shutdown_callback ( struct rclc_executor_t *  executor,
rclc_shutdown_callback_t  callback,
void *  context,
rclc_shutdown_callback_handle_t *  out_handle 
)

Register a callback to run BEFORE the executor's session is closed.

Issue 0790. This is the phase with no workaround: the callback runs while every entity still works, so a node can publish a final state, answer a last request, park an actuator or release a bus. After teardown it cannot.

On success writes the handle through out_handle and returns RCL_RET_OK. Returns RCLC_RET_FULL when the phase's fixed table is exhausted (build-time NROS_EXECUTOR_MAX_SHUTDOWN_CBS, default 2).

The hooks run when the executor is finalized — rclc_executor_fini(), or whatever tears the executor down. They are a CLEAN-STOP facility: a watchdog reset, a hard fault or an abort does not come through here.

Safety

  • executor must be a valid pointer to an initialized executor.
  • out_handle must be a valid pointer.
  • callback must be safe to invoke once with context, and context must stay valid until the hook runs or is removed.

◆ rclc_executor_add_service_raw()

rcl_ret_t rclc_executor_add_service_raw ( struct rclc_executor_t *  executor,
struct rcl_service_t *  service,
rclc_service_raw_callback_t  callback,
void *  context 
)

phase-417 stage 6 — register a service server, supplying its request callback HERE rather than at *_init.

rclc_service_init_default takes no callback (rclc's arity), so the handler that used to ride on nros_service_init is supplied at registration — the call rclc calls rclc_executor_add_service. The nros_ prefix is kept for the same reason as rclc_executor_add_subscription_raw: rclc's rclc_executor_add_service carries caller-owned request_msg / response_msg storage and a void (*)(const void *, void *) handler, while ours is a CDR-byte handler that RETURNS a value. Same capability, different signature, and only a signature can carry a name. A generated <Srv>_executor_add_service(executor, service, &handler) wraps it for the typed path.

The arena entry owns callback and context; the service struct keeps neither (phase-487 W2). This replaced the two-argument nros_executor_add_service, which dispatched a callback an init call had stored in the struct.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT for a NULL callback
  • RCLC_RET_FULL when the executor has no handle left
  • RCL_RET_ERROR when the server could not be created

Safety

  • Both pointers must reference initialized objects.
  • context is passed through untouched and may be NULL.

◆ rclc_executor_add_subscription_in_group()

rcl_ret_t rclc_executor_add_subscription_in_group ( struct rclc_executor_t *  executor,
struct rcl_subscription_t *  subscription,
rclc_subscription_raw_callback_t  callback,
void *  context,
enum rclc_executor_handle_invocation_t  invocation,
const char *  callback_group 
)

Phase 273 (RFC-0047) — register a subscription in a named callback group.

Identical to [rclc_executor_add_subscription_raw] but additionally passes the group name to the executor so the seeded group_sched_table can bind the callback to the group's SchedContext. callback_group may be NULL or an empty string — both behave identically to rclc_executor_add_subscription_raw.

phase-487 W1 — callback and context are arguments here, as on the _raw path; the subscription struct no longer stores them.

Safety

All non-NULL pointers must be valid and point to initialized objects.

◆ rclc_executor_add_subscription_raw()

rcl_ret_t rclc_executor_add_subscription_raw ( struct rclc_executor_t *  executor,
struct rcl_subscription_t *  subscription,
rclc_subscription_raw_callback_t  callback,
void *  context,
enum rclc_executor_handle_invocation_t  invocation 
)

phase-417 stage 6 — register a BYTE-oriented subscription, supplying its callback HERE rather than at *_init.

This is the raw-path sibling of [rclc_executor_add_subscription_with_context]. rclc_subscription_init_default takes no callback (rclc's arity), so the byte callback that used to ride on nros_subscription_init is supplied at registration, which is where rclc supplies it (rclc_executor_add_subscription). The name keeps the nros_ prefix deliberately: rclc's add_subscription delivers a DESERIALIZED message into caller storage, so the byte path has no upstream counterpart and must not wear its name (RFC-0089's compile-or-conform rule — a plausible name over an opposite data contract is the defect the RFC exists to prevent).

The arena entry owns callback and context from here on; the subscription struct keeps neither (phase-487 W1). This replaced the three-argument nros_executor_add_subscription, which dispatched the callback an init call had stored in the struct.

Returns

As [rclc_executor_add_subscription_with_context]; RCL_RET_INVALID_ARGUMENT for a NULL callback, since an entry with nothing to dispatch would hold a subscriber and a slot for no reader.

Safety

  • executor and subscription must be valid, initialised objects.
  • context is passed through untouched and may be NULL.

◆ rclc_executor_add_subscription_raw_validated()

rcl_ret_t rclc_executor_add_subscription_raw_validated ( struct rclc_executor_t *  executor,
struct rcl_subscription_t *  subscription,
rclc_subscription_validated_callback_t  callback,
void *  context,
enum rclc_executor_handle_invocation_t  invocation 
)

phase-492 W4 — register a raw subscription whose callback also receives the sample's E2E integrity status (CRC + sequence gap / duplicate): the C API's form of what a C component used to reach through the C++ FFI (nros_cpp_subscription_register_validated), and the callback-style sibling of rclc_polling_subscription_take_validated.

Requires the safety-e2e capability on both the runtime and the backend (NROS_SAFETY_E2E=ON); without it this answers RCL_RET_UNSUPPORTED.

Safety

  • executor and subscription must be valid, initialised objects.
  • context is passed through untouched and may be NULL.

◆ rclc_executor_add_subscription_raw_with_info()

rcl_ret_t rclc_executor_add_subscription_raw_with_info ( struct rclc_executor_t *  executor,
const struct rcl_node_t *  node,
const char *  topic_name,
const char *  type_name,
const char *  type_hash,
const struct rclc_qos_t *  qos,
rclc_subscription_info_callback_t  callback,
void *  context 
)

Phase 189.M3.4 — register a raw subscription whose callback also receives the sample's wire attachment (the C analog of the Rust node.subscription(t).generic(..).message_info() builder; rclc's generic-with-info subscription). Direct-arg form (no rcl_subscription_t struct): the callback signature differs from the plain rclc_subscription_raw_callback_t, so this is its own entry point rather than a flag on rclc_executor_add_subscription_raw.

Not removable (issue 1668): it takes no subscription object and hands back nothing, so its entry — slot, arena bytes and subscriber — lives until rclc_executor_fini. Kept for ABI compatibility (RFC-0054 is additive). Prefer [rclc_executor_add_subscription_with_info], which registers the same entry into a rcl_subscription_t that rclc_executor_remove_subscription takes back out.

node may be NULL (legacy single-Node path) or a Node created via rclc_executor_node_init (routes to that Node's session). qos may be NULL (defaults). Cross-RMW bridges read the bridge_origin tag from the attachment for echo suppression.

Safety

All non-NULL pointers must be valid; the C strings must be NUL-terminated UTF-8 valid for the duration of the call.

◆ rclc_executor_add_subscription_with_context()

rcl_ret_t rclc_executor_add_subscription_with_context ( struct rclc_executor_t *  executor,
struct rcl_subscription_t *  subscription,
void *  msg,
rclc_subscription_callback_with_context_t  callback,
void *  context,
enum rclc_executor_handle_invocation_t  invocation 
)

rclc's rclc_executor_add_subscription_with_context, argument for argument (phase-492 W8):

@ ON_NEW_DATA
Definition nros_generated.h:660
rcl_ret_t rclc_executor_add_subscription_with_context(struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, void *msg, rclc_subscription_callback_with_context_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)

The deserialiser and the receive-buffer hint come from the descriptor the subscription was created with (ROSIDL_GET_MSG_TYPE_SUPPORT(...), kept on the struct by rclc_subscription_init_*), which is why this takes no more arguments than rclc's. Before phase-492 the descriptor had no codec, so the typed registration carried a seventh argument and a generated per-type macro collapsed it away; both are gone.

The CONTEXT-LESS rclc_executor_add_subscription (a void (*)(const void*) callback) stays refused: adapting it needs a trampoline that remembers the original function pointer, and state in the wrapper is RFC-0019/0020's violation rather than an ergonomic. <rcl/types.h> records the refusal.

No allocator is involved, and none is needed. The caller owning msg (its strings and sequences wired by <Msg>__init_in) IS the mechanism — the same one rclc uses.

What the callback sees when decoding fails

Nothing — it is not called. A sample that does not decode (malformed, or a string or sequence longer than the capacity the caller wired) is dropped, counted as a subscription_errors in the spin result, and logged (rate-limited) with its length and the return code. Dispatching anyway would hand the callback the PREVIOUS message as if it were the new one.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT — a NULL executor / subscription / msg / callback
  • RCL_RET_UNSUPPORTED — the subscription's descriptor carries no deserialiser (one built from type names alone); register it with rclc_executor_add_subscription_raw instead
  • otherwise as the raw registration

Safety

  • executor and subscription must be valid, initialised objects.
  • msg must point to writable storage of the subscription's type and stay valid for as long as the subscription is registered. Nothing here allocates it, copies it, or frees it.

◆ rclc_executor_add_subscription_with_info()

rcl_ret_t rclc_executor_add_subscription_with_info ( struct rclc_executor_t *  executor,
struct rcl_subscription_t *  subscription,
rclc_subscription_info_callback_t  callback,
void *  context,
enum rclc_executor_handle_invocation_t  invocation 
)

Issue 1668 — register a raw subscription whose callback also receives the sample's wire attachment, into a rcl_subscription_t the caller keeps, so it can be REMOVED.

The removable sibling of [rclc_executor_add_subscription_raw_with_info], in the rclc shape every other subscription add has — the info-callback twin of [rclc_executor_add_subscription_raw]:

rclc_subscription_init_default(&sub, &node, &type, "/topic");
rclc_executor_add_subscription_with_info(&exec, &sub, on_sample, ctx,
...
rclc_executor_remove_subscription(&exec, &sub);
rcl_ret_t rcl_subscription_fini(struct rcl_subscription_t *subscription, struct rcl_node_t *node)
rcl_ret_t rclc_executor_add_subscription_with_info(struct rclc_executor_t *executor, struct rcl_subscription_t *subscription, rclc_subscription_info_callback_t callback, void *context, enum rclc_executor_handle_invocation_t invocation)
rcl_ret_t rclc_subscription_init_default(struct rcl_subscription_t *subscription, const struct rcl_node_t *node, const struct rclc_message_type_t *type_info, const char *topic_name)

Topic, type, hash, QoS and node come from the subscription (a caller that holds only type-name strings builds a rclc_message_type_t from them — its fields are the same two strings the direct-arg form takes). The entry is the one the direct-arg form registers; what differs is that the subscription records (handle, executor) and the trigger table names it, so rclc_executor_remove_subscription releases it and rclc_executor_trigger_one can name it. The subscription's own plain callback field is left untouched; callback here is the one dispatched.

Returns

As [rclc_executor_add_subscription_raw]; RCL_RET_INVALID_ARGUMENT for a NULL callback.

Safety

  • executor and subscription must be valid, initialised objects.
  • context is passed through untouched and may be NULL.

◆ rclc_executor_add_time_triggered_dispatcher()

rcl_ret_t rclc_executor_add_time_triggered_dispatcher ( struct rclc_executor_t *  executor,
uint32_t  major_frame_us 
)

Phase 110.G — enable TT dispatch on this executor by setting the major-frame length in microseconds. 0 disables the gate.

Safety

executor must be a valid pointer to an initialized executor.

◆ rclc_executor_add_timer()

rcl_ret_t rclc_executor_add_timer ( struct rclc_executor_t *  executor,
struct rcl_timer_t *  timer 
)

Add a timer to the executor.

Wraps the C timer callback in a closure and registers it with the internal nros-node executor.

Safety

  • All pointers must be valid and point to initialized objects

◆ rclc_executor_add_timer_in_group()

rcl_ret_t rclc_executor_add_timer_in_group ( struct rclc_executor_t *  executor,
struct rcl_timer_t *  timer,
const char *  callback_group 
)

Phase 273 (RFC-0047) — register a timer in a named callback group.

Identical to rclc_executor_add_timer but additionally passes the group name so the seeded group_sched_table can bind the callback to the group's SchedContext. callback_group may be NULL or empty — both behave identically to rclc_executor_add_timer.

Safety

All non-NULL pointers must be valid and point to initialized objects.

◆ rclc_executor_attach_action_client()

rcl_ret_t rclc_executor_attach_action_client ( struct rclc_executor_t *  executor,
struct rcl_action_client_t *  client 
)

Register an action client with the executor for async (non-blocking) operation.

After registration, rclc_executor_spin_some polls the action client's pending requests (goal response, feedback, result) and invokes the registered callbacks.

The action client must already be initialized via rcl_action_client_init. Callbacks should be set via rclc_action_client_set_goal_response_callback, rclc_action_client_set_feedback_callback, and rclc_action_client_set_result_callback before or after this call.

Safety

  • executor and client must be valid pointers to initialized structs.

◆ rclc_executor_attach_action_server()

rcl_ret_t rclc_executor_attach_action_server ( struct rclc_executor_t *  executor,
struct rcl_action_server_t *  server 
)

Add an action server to the executor.

Extracts metadata from the action server struct, creates callback trampolines, and registers with the internal executor.

Safety

  • All pointers must be valid and point to initialized objects

◆ rclc_executor_attach_client()

rcl_ret_t rclc_executor_attach_client ( struct rclc_executor_t *  executor,
struct rcl_client_t *  client 
)

Add a service client to the executor (Phase 82).

Creates the underlying RmwServiceClient inside the executor's arena and stashes the executor pointer + arena entry index into the client's _internal blob so subsequent calls to rclc_client_call, rclc_client_send_request_async, and friends can drive the executor without taking it as an explicit argument.

Must be called exactly once after rclc_client_init_default and before any send/call. Calling it twice on the same client returns RCLC_RET_BAD_SEQUENCE.

Safety

  • Both pointers must reference initialized objects.

◆ rclc_executor_bind_handle_to_sched_context()

rcl_ret_t rclc_executor_bind_handle_to_sched_context ( struct rclc_executor_t *  executor,
size_t  handle,
rclc_sched_context_id_t  sc_id 
)

Bind a registered callback to a scheduling context. The next spin_once cycle dispatches that callback through the SC's queue (FIFO bitmap or EDF heap, in the SC's priority bucket). Phase 110.B.

handle is the index returned by the corresponding nros_executor_add_* call. sc_id must be a value previously returned from [rclc_executor_create_sched_context] (or 0 for the auto-created default Fifo SC).

Returns RCL_RET_INVALID_ARGUMENT for an out-of-range handle, an empty entry slot, or an unknown sc_id.

Safety

executor must be a valid pointer to an initialized executor.

◆ rclc_executor_cancel()

rcl_ret_t rclc_executor_cancel ( struct rclc_executor_t *  executor)

Ask a spinning executor to stop — rclcpp::Executor::cancel / rcl's context shutdown, phase-417 W4.c.

Renamed from nros_executor_stop, whose deprecated static inline forwarder in <rclc/executor.h> was retired by phase-417 stage 6 step B. Three of our own languages had three answers to "stop spinning"; cancel is ROS 2's.

ADOPT-BOUNDED (RFC-0089)

cancel sets a flag the spin loop observes at the NEXT POLL BOUNDARY, so it returns BEFORE spinning has actually stopped; [rclc_executor_is_spinning] is the observable that tells you when it has. The boundary is one spin_once timeout wide (rclc_executor_set_timeout).

It does NOT tear down the session: the executor stays initialised, keeps its entities, and can be spun again. rclc_executor_fini is the other verb.

Safe to call from a signal handler or another thread.

Safety

  • executor must be a valid pointer

◆ rclc_executor_count_publishers()

rcl_ret_t rclc_executor_count_publishers ( struct rclc_executor_t *  executor,
const char *  topic_name,
size_t *  out_count 
)

phase-381 W4 — how many publishers are visible on topic_name.

topic_name is a ROS name ("/chatter"). The count reflects what has been DISCOVERED, so it can be low right after startup and is never a proof of absence.

Safety

  • executor must point to an initialised executor.
  • topic_name must be a valid NUL-terminated string.
  • out_count must be writable.

◆ rclc_executor_count_subscribers()

rcl_ret_t rclc_executor_count_subscribers ( struct rclc_executor_t *  executor,
const char *  topic_name,
size_t *  out_count 
)

phase-381 W4 — how many subscribers are visible on topic_name. See rclc_executor_count_publishers for the caveats.

Safety

  • executor must point to an initialised executor.
  • topic_name must be a valid NUL-terminated string.
  • out_count must be writable.

◆ rclc_executor_create_sched_context()

rcl_ret_t rclc_executor_create_sched_context ( struct rclc_executor_t *  executor,
const struct rclc_sched_context_t *  cfg,
rclc_sched_context_id_t *  out_sc_id 
)

Register a new scheduling context with the executor. Phase 110.B.

On success writes the new SchedContextId through out_sc_id and returns RCL_RET_OK. Returns RCLC_RET_FULL when no slot is available (build-time NROS_EXECUTOR_MAX_SC exhausted).

Safety

All pointers must be valid and the executor initialized.

◆ rclc_executor_default_sched_context_id()

rclc_sched_context_id_t rclc_executor_default_sched_context_id ( void  )

Identifier of the auto-created default Fifo-class SC. Every callback registered without an explicit binding maps to it. Phase 110.B.

◆ rclc_executor_fini()

rcl_ret_t rclc_executor_fini ( struct rclc_executor_t *  executor)

Finalize an executor.

IDEMPOTENT: a zero-initialised executor is not an error and returns RCL_RET_OK (phase-417 stage 3, the same sweep as rcl_guard_condition_fini / rcl_node_fini). rclc says so in a comment of its own — rclc/src/rclc/executor.c @ humble: } else { // Repeated calls to fini or calling fini on a zero initialized executor is ok } followed by return RCL_RET_OK;. Ours returned RCL_RET_NOT_INIT.

Safety

  • executor must be a valid pointer

◆ rclc_executor_get_arena_capacity()

size_t rclc_executor_get_arena_capacity ( const struct rclc_executor_t *  executor)

Total bytes of arena this executor was given (NROS_EXECUTOR_ARENA_SIZE as carved from its inline backing). 0 for NULL or an executor that is not initialised.

Safety

executor must be NULL or a valid pointer.

◆ rclc_executor_get_arena_used()

size_t rclc_executor_get_arena_used ( const struct rclc_executor_t *  executor)

Bytes of the executor's arena currently claimed — its high-water mark.

Issue 1609 — the arena is a bump allocator with a free list of released regions (issue 1496): a registration first reuses a released region that fits and only then moves the bump pointer, so this number grows only when a registration found nothing to reuse. A create / remove loop whose value stays at the first cycle's is reusing its bytes; one that climbs is leaking them. Pair it with rclc_executor_get_arena_capacity for the headroom.

Returns 0 for NULL or an executor that is not initialised.

Safety

executor must be NULL or a valid pointer.

◆ rclc_executor_get_client_names_and_types_by_node()

rcl_ret_t rclc_executor_get_client_names_and_types_by_node ( struct rclc_executor_t *  executor,
const char *  node_name,
const char *  node_namespace,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — what services one named node CALLS, with the types.

Safety

As rclc_executor_get_publisher_names_and_types_by_node.

◆ rclc_executor_get_handle_count()

int rclc_executor_get_handle_count ( const struct rclc_executor_t *  executor)

Get the number of handles in the executor.

◆ rclc_executor_get_node_names()

rcl_ret_t rclc_executor_get_node_names ( struct rclc_executor_t *  executor,
rclc_node_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — every node on the graph, with its namespace.

A VISITOR rather than an out-array: upstream's rcutils_string_array_t allocates two levels deep, there is no allocator here, and a caller-provided buffer needs a bound the caller cannot know. Peak extra memory is one entry, and a caller with its own limit stops by returning false.

Reports what has been DISCOVERED; never blocks. The first call after startup legitimately sees a partial graph — the backend keeps a standing query fed by the spin loop. Poll rather than calling once and concluding: an empty enumeration means "nobody seen yet", never "nobody exists".

Returns

  • RCL_RET_OK — enumeration ran (possibly visiting nothing).
  • RCL_RET_UNSUPPORTED — this backend has no graph. DISTINCT from an empty graph, deliberately.
  • RCL_RET_NOT_INIT — executor not initialised.
  • RCL_RET_INVALID_ARGUMENT — executor or visit is NULL.

Safety

  • executor must point to an initialised executor.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_publisher_names_and_types_by_node()

rcl_ret_t rclc_executor_get_publisher_names_and_types_by_node ( struct rclc_executor_t *  executor,
const char *  node_name,
const char *  node_namespace,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — what one named node PUBLISHES, with the types.

Safety

  • executor must point to an initialised executor.
  • node_name / node_namespace must be valid NUL-terminated strings.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_publishers_info_by_topic()

rcl_ret_t rclc_executor_get_publishers_info_by_topic ( struct rclc_executor_t *  executor,
const char *  topic_name,
rclc_endpoint_info_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — the publishers on topic_name, one visit each.

Safety

  • executor must point to an initialised executor.
  • topic_name must be a valid NUL-terminated string.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_remaining_handles()

int rclc_executor_get_remaining_handles ( const struct rclc_executor_t *  executor)

Get remaining total handle capacity.

◆ rclc_executor_get_service_names_and_types()

rcl_ret_t rclc_executor_get_service_names_and_types ( struct rclc_executor_t *  executor,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — every service on the graph, with its types. As rclc_executor_get_topic_names_and_types, over servers and clients.

Safety

  • executor must point to an initialised executor.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_service_names_and_types_by_node()

rcl_ret_t rclc_executor_get_service_names_and_types_by_node ( struct rclc_executor_t *  executor,
const char *  node_name,
const char *  node_namespace,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — what services one named node SERVES, with the types.

Safety

As rclc_executor_get_publisher_names_and_types_by_node.

◆ rclc_executor_get_subscriber_names_and_types_by_node()

rcl_ret_t rclc_executor_get_subscriber_names_and_types_by_node ( struct rclc_executor_t *  executor,
const char *  node_name,
const char *  node_namespace,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — what one named node SUBSCRIBES to, with the types.

**subscriber, not subscription** — rcl spells it rcl_get_subscriber_names_and_types_by_node, and the C surface takes its vocabulary from rcl so a user porting C ROS 2 code types what they already know. The C++ and Rust surfaces say subscription because rclcpp and rclrs do. Three layers, three upstreams, one word each — not drift. Issue 0788 owns the wider verb sweep.

Safety

  • executor must point to an initialised executor.
  • node_name / node_namespace must be valid NUL-terminated strings.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_subscriptions_info_by_topic()

rcl_ret_t rclc_executor_get_subscriptions_info_by_topic ( struct rclc_executor_t *  executor,
const char *  topic_name,
rclc_endpoint_info_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — the subscriptions on topic_name, one visit each.

Safety

As rclc_executor_get_publishers_info_by_topic.

◆ rclc_executor_get_topic_names_and_types()

rcl_ret_t rclc_executor_get_topic_names_and_types ( struct rclc_executor_t *  executor,
rclc_names_and_types_visit_fn  visit,
void *  ctx 
)

phase-381 W4 — every topic on the graph, with the types on it.

Called once per distinct TOPIC: a topic carrying two types is one call with two entries, not two calls. types_count may legitimately be 0 on a partially discovered graph — reporting the name without a type beats dropping it.

Same discovery caveat as rclc_executor_get_node_names: an empty enumeration means "nobody seen yet", not "nobody exists".

Returns

  • RCL_RET_OK — enumeration ran (possibly visiting nothing).
  • RCL_RET_UNSUPPORTED — this backend has no graph.
  • RCL_RET_NOT_INIT — executor not initialised.
  • RCL_RET_INVALID_ARGUMENT — executor or visit is NULL.

Safety

  • executor must point to an initialised executor.
  • visit must be callable for the duration of the call.

◆ rclc_executor_get_zero_initialized_executor()

struct rclc_executor_t rclc_executor_get_zero_initialized_executor ( void  )

Get a zero-initialized executor.

◆ rclc_executor_init()

rcl_ret_t rclc_executor_init ( struct rclc_executor_t *  executor,
struct rcl_context_t *  context,
size_t  number_of_handles,
const struct rcl_allocator_t *  allocator 
)

Initialize an executor — rclc's signature (phase-492 W1.b).

rclc_executor_init(&executor, &support.context, n, &allocator), as an rclc program writes it. context must be the context member of an initialised rclc_support_t; that support's session is the one the executor drives. allocator must be NULL or rcl_get_default_allocator()'s (the executor lives in its own _opaque; nothing is allocated).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if executor is NULL, number_of_handles is 0, or allocator is one we would have to ignore
  • RCL_RET_NOT_INIT if context names no initialised support

Safety

executor must be valid for writes; context and allocator NULL or readable.

◆ rclc_executor_is_spinning()

bool rclc_executor_is_spinning ( const struct rclc_executor_t *  executor)

Is a blocking spin (rclc_executor_spin / _spin_period) running on this executor right now? phase-417 W4.c — rclcpp::Executor::is_spinning.

The C API has always MODELLED this (RCLC_EXECUTOR_STATE_SPINNING) and never exported a way to ask, so a C caller could stop a spin but not observe that it had stopped — the second half of [rclc_executor_cancel]'s envelope had no reader.

A DIFFERENT question from "was cancel requested": between cancel() and the loop's next poll boundary the request is in and the spin is still running. This answers the second, which is the one a caller waits on.

false for a null pointer — "no executor" is not spinning, and this is a predicate with no error channel.

Safety

  • executor must be null or a valid pointer

◆ rclc_executor_is_valid()

bool rclc_executor_is_valid ( const struct rclc_executor_t *  executor)

Check if executor is valid (initialized).

◆ rclc_executor_lifecycle_change_state()

rcl_ret_t rclc_executor_lifecycle_change_state ( struct rclc_executor_t *  executor,
uint8_t  transition_id 
)

Trigger a lifecycle transition on the executor's state machine.

Safety

Invokes the user's registered C callback through a raw function pointer. The caller must ensure the callback and any context it captures are live.

◆ rclc_executor_lifecycle_get_current_state()

uint8_t rclc_executor_lifecycle_get_current_state ( struct rclc_executor_t *  executor)

Get the current lifecycle state of the executor's state machine.

Returns RCLC_LIFECYCLE_STATE_UNCONFIGURED if services are not registered yet.

Takes *mut rather than *const because get_executor returns &mut CExecutor — reading the state is logically read-only but the executor accessor shares storage with the services loop that needs &mut during spin.

◆ rclc_executor_lifecycle_register_on_activate()

rcl_ret_t rclc_executor_lifecycle_register_on_activate ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-activate callback on the executor's state machine.

◆ rclc_executor_lifecycle_register_on_cleanup()

rcl_ret_t rclc_executor_lifecycle_register_on_cleanup ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-cleanup callback on the executor's state machine.

◆ rclc_executor_lifecycle_register_on_configure()

rcl_ret_t rclc_executor_lifecycle_register_on_configure ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-configure callback on the executor's state machine.

◆ rclc_executor_lifecycle_register_on_deactivate()

rcl_ret_t rclc_executor_lifecycle_register_on_deactivate ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-deactivate callback on the executor's state machine.

◆ rclc_executor_lifecycle_register_on_error()

rcl_ret_t rclc_executor_lifecycle_register_on_error ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-error callback on the executor's state machine.

◆ rclc_executor_lifecycle_register_on_shutdown()

rcl_ret_t rclc_executor_lifecycle_register_on_shutdown ( struct rclc_executor_t *  executor,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register the on-shutdown callback on the executor's state machine.

◆ rclc_executor_node_init()

rcl_ret_t rclc_executor_node_init ( struct rclc_executor_t *  executor,
struct rcl_node_t *  node,
const char *  name,
const struct rcl_node_options_t *  options 
)

Phase 104.C.8.b — initialize a Node via the executor's [node_builder](nros_node::Executor::node_builder) chain.

Thin wrapper over Rust's executor.node_builder(name).rmw(...).locator(...).domain_id(...). namespace(...).sched(...).build(). Materialises a Node inside the executor's node table and stores the returned NodeId in node.node_id so subsequent [rclc_executor_add_subscription_raw] / _service / _client / _action_* calls route through register_*_on(NodeId, ...) instead of the legacy single-Node path.

Replaces the pre-104.C ordering of support_init → node_init → executor_init with the rclcpp-aligned support_init → executor_init → executor_node_init. The old rclc_node_init_default / rclc_node_init_ex entry points are preserved for source compatibility — they still drive the single-Node legacy path and leave node.node_id = 0.

Parameters

  • executor — Pointer to an initialised executor.
  • node — Pointer to a zero-initialised node. Populated on success.
  • name — Node name (null-terminated). Must not be NULL.
  • options — Pointer to populated rcl_node_options_t. NULL = default options (no rmw override, inherits executor's locator
    • domain, executor-default SchedContext).

Returns

  • RCL_RET_OK on success.
  • RCL_RET_INVALID_ARGUMENT on NULL pointers / bad strings.
  • RCLC_RET_BAD_SEQUENCE if node is already initialised.
  • RCL_RET_NOT_INIT if executor isn't initialised.
  • RCL_RET_ERROR if the executor's node table is full (NROS_EXECUTOR_MAX_NODES) or the backend session open failed.

Safety

All pointer arguments must satisfy their per-parameter rules. options length fields must not overrun their buffers.

◆ rclc_executor_ping()

rcl_ret_t rclc_executor_ping ( struct rclc_executor_t *  executor,
int32_t  timeout_ms 
)

Phase 124.F.3 — session-level connectivity probe.

Sends a wire-level round-trip ("is the peer / agent / router reachable?") and waits up to timeout_ms. Mirrors micro-ROS's rmw_uros_ping_agent. Useful for reconnect-on-link-loss patterns: bare-metal code calls ping(100) periodically and tears down / re-opens the session on timeout.

Returns

  • RCL_RET_OK — peer responded within budget.
  • RCL_RET_TIMEOUT — no reply before timeout_ms.
  • RCL_RET_UNSUPPORTED — active backend can't probe.
  • RCL_RET_NOT_INIT — executor not initialised.
  • RCL_RET_INVALID_ARGUMENT — executor is NULL.

Safety

  • executor must be a valid pointer to an initialized executor.

◆ rclc_executor_register_lifecycle_services()

rcl_ret_t rclc_executor_register_lifecycle_services ( struct rclc_executor_t *  executor)

Register the five REP-2002 lifecycle services on the executor's node.

After this call, ros2 lifecycle set|get|list|nodes can drive the executor-owned state machine. Register transition callbacks via nros_executor_lifecycle_register_on_* and inspect the state via rclc_executor_lifecycle_get_current_state.

◆ rclc_executor_remove_action_client()

rcl_ret_t rclc_executor_remove_action_client ( struct rclc_executor_t *  executor,
struct rcl_action_client_t *  client 
)

Remove an action client from the executor — issue 1609.

The client half of [rclc_executor_remove_action_server], with the same three tables and the same reason: the arena entry rclc_executor_attach_action_client registered holds client itself as its callback context, and rcl_action_client_fini cannot reach the executor to undo it. The entry is dropped in place (Executor::release_action_client_raw, the default-sized form the add used) — its three service clients and feedback subscription are destroyed and its slot and bytes are reused — handle_count comes back down, and the trigger table forgets the client.

The client stays INITIALIZED (re-addable, or finalisable with rcl_action_client_fini). Any goal it was waiting on is abandoned with the entry.

Returns

As [rclc_executor_remove_action_server].

Safety

executor and client must be valid pointers to initialised objects.

◆ rclc_executor_remove_action_server()

rcl_ret_t rclc_executor_remove_action_server ( struct rclc_executor_t *  executor,
struct rcl_action_server_t *  server 
)

Remove an action server from the executor — issue 1609, the C twin of issue 1496's resolution 2.

rclc_executor_attach_action_server registers an arena entry whose callback context is &server->_internal, and rcl_action_server_fini does not (and cannot) undo it: fini is handed only the entity, and the executor's own tables — handle_count and the trigger entity table — live in the rclc_executor_t it never sees. This is the call that can, in rclc's shape (rclc_executor_remove_*: the executor and the entity).

It undoes all three tables at once:

  • the arena entry is DROPPED in place (Executor::release_action_server_raw_sized, with the same const parameters the add used) — the action's three service servers and two publishers are destroyed, so it LEAVES THE GRAPH and no late goal can reach server; its callback slot is freed and its arena bytes go on the executor's free list, where the next registration reuses them;
  • handle_count comes back down, so a create/remove loop never hits max_handles;
  • the trigger table's entity pointer for the slot is cleared.

The server stays INITIALIZED: it can be re-added, or finalised with rcl_action_server_fini. Call this BEFORE fini and before the rcl_action_server_t storage goes away. A server that is never removed keeps its entry until rclc_executor_fini, which drops every entry.

Returns

  • RCL_RET_OK — removed.
  • RCL_RET_INVALID_ARGUMENT — a NULL pointer.
  • RCL_RET_NOT_INIT — the executor or the server is not initialised.
  • RCLC_RET_NOT_FOUND — the server is not registered on THIS executor.
  • RCLC_RET_REENTRANT — called from inside a callback this executor is dispatching; the entry may be the one running.

Safety

executor and server must be valid pointers to initialised objects.

◆ rclc_executor_remove_client()

rcl_ret_t rclc_executor_remove_client ( struct rclc_executor_t *  executor,
const struct rcl_client_t *  client 
)

Remove a service client from the executor — issue 1631, rclc's rclc_executor_remove_client.

Until phase-487 W2 the arena entry rclc_executor_attach_client registered dispatched replies through a trampoline that READ the rcl_client_t, so after rcl_client_fini alone a late reply was a use-after-free of a stack or freed client; the entry now holds the user's callback itself. This drops the entry (the client leaves the graph, and a reply it was still waiting for is abandoned), undoes handle_count and the trigger table, and returns the client from REGISTERED to INITIALIZED — so it can be re-added, or finalised with rcl_client_fini. Its timeout setting is kept.

Returns

As [rclc_executor_remove_subscription].

Safety

executor and client must be valid pointers to initialised objects.

◆ rclc_executor_remove_on_shutdown_callback()

rcl_ret_t rclc_executor_remove_on_shutdown_callback ( struct rclc_executor_t *  executor,
rclc_shutdown_callback_handle_t  handle 
)

Remove a previously registered on-shutdown callback. See [rclc_executor_remove_pre_shutdown_callback].

Safety

executor must be a valid pointer to an initialized executor.

◆ rclc_executor_remove_pre_shutdown_callback()

rcl_ret_t rclc_executor_remove_pre_shutdown_callback ( struct rclc_executor_t *  executor,
rclc_shutdown_callback_handle_t  handle 
)

Remove a previously registered pre-shutdown callback.

Returns RCL_RET_OK when handle named a live hook, RCLC_RET_NOT_FOUND when it did not — including a handle that was already removed, and a handle issued by rclc_executor_add_on_shutdown_callback (the phase is part of the handle, so it cannot cross over and remove the wrong hook).

Safety

executor must be a valid pointer to an initialized executor.

◆ rclc_executor_remove_service()

rcl_ret_t rclc_executor_remove_service ( struct rclc_executor_t *  executor,
const struct rcl_service_t *  service 
)

Remove a service server from the executor — issue 1631, rclc's rclc_executor_remove_service.

Drops the arena entry rclc_executor_add_service_raw registered (the server leaves the graph; its slot and bytes are reused) and undoes handle_count, service_count and the trigger table, as [rclc_executor_remove_subscription] does. The service stays INITIALIZED.

Returns

As [rclc_executor_remove_subscription].

Safety

executor and service must be valid pointers to initialised objects.

◆ rclc_executor_remove_subscription()

rcl_ret_t rclc_executor_remove_subscription ( struct rclc_executor_t *  executor,
const struct rcl_subscription_t *  subscription 
)

Remove a subscription from the executor — issue 1631, rclc's rclc_executor_remove_subscription.

Every nros_executor_add_subscription* that takes a rcl_subscription_t registers an arena entry and records it in the subscription; rcl_subscription_fini is handed only the subscription, so it cannot undo the executor's side. This does, the way [rclc_executor_remove_action_server] does for an action: the arena entry is DROPPED (the subscriber leaves the graph, its callback slot and its arena bytes — receive ring included — are reused by the next registration), handle_count and subscription_count come back down, and the trigger table forgets the subscription.

The subscription stays INITIALIZED: it can be re-added, or finalised with rcl_subscription_fini. Call this BEFORE fini. Typed message storage handed to rclc_executor_add_subscription_with_context is not written again after this returns.

Returns

  • RCL_RET_OK — removed.
  • RCL_RET_INVALID_ARGUMENT — a NULL pointer.
  • RCL_RET_NOT_INIT — the executor or the subscription is not initialised.
  • RCLC_RET_NOT_FOUND — the subscription is not registered on THIS executor.
  • RCLC_RET_REENTRANT — called from inside a callback this executor is dispatching; the entry may be the one running.

Safety

executor and subscription must be valid pointers to initialised objects.

◆ rclc_executor_remove_timer()

rcl_ret_t rclc_executor_remove_timer ( struct rclc_executor_t *  executor,
const struct rcl_timer_t *  timer 
)

Remove a timer from the executor — issue 1631, rclc's rclc_executor_remove_timer.

The arena entry rclc_executor_add_timer / rclc_executor_add_timer_in_group registered wraps the timer's C callback in a closure that captured the rcl_timer_t * itself, so after rcl_timer_fini alone it kept firing with a pointer to the finalised (or freed) struct. This drops the entry — the closure with it — and undoes handle_count, timer_count and the trigger table, as [rclc_executor_remove_subscription] does.

The timer keeps its state (RUNNING or CANCELED) and can be re-added, or finalised with rcl_timer_fini. Call this BEFORE fini.

Returns

As [rclc_executor_remove_subscription].

Safety

executor and timer must be valid pointers to initialised objects.

◆ rclc_executor_set_semantics()

rcl_ret_t rclc_executor_set_semantics ( struct rclc_executor_t *  executor,
enum rclc_executor_semantics_t  semantics 
)

Set data communication semantics.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_set_timeout()

rcl_ret_t rclc_executor_set_timeout ( struct rclc_executor_t *  executor,
uint64_t  timeout_ns 
)

Set the executor timeout.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_set_trigger()

rcl_ret_t rclc_executor_set_trigger ( struct rclc_executor_t *  executor,
rclc_executor_trigger_t  trigger,
void *  context 
)

Set the trigger condition for the executor.

context is rclc's trigger_object: it is handed to trigger unchanged on every cycle. For rclc_executor_trigger_one it is the ENTITY pointer — rclc_executor_set_trigger(&exec, rclc_executor_trigger_one, &my_sub).

Safety

  • executor must be a valid pointer to an initialized executor
  • executor must not be moved or copied while the trigger is installed — the internal executor holds its address so the trigger can be given the handle array.

◆ rclc_executor_spin()

rcl_ret_t rclc_executor_spin ( struct rclc_executor_t *  executor)

Spin the executor forever.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_spin_one_period()

rcl_ret_t rclc_executor_spin_one_period ( struct rclc_executor_t *  executor,
uint64_t  period_ns 
)

Spin the executor for one period.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_spin_period()

rcl_ret_t rclc_executor_spin_period ( struct rclc_executor_t *  executor,
uint64_t  period_ns 
)

Spin the executor with a fixed period.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_spin_some()

rcl_ret_t rclc_executor_spin_some ( struct rclc_executor_t *  executor,
uint64_t  timeout_ns 
)

Spin the executor once.

Drives middleware I/O, then dispatches ready callbacks.

Returns

RCL_RET_OK for any completed cycle, whether or not a callback ran — rclc discards the wait's timeout, so an idle tick is a success. See spin_cycle_ret.

Safety

  • executor must be a valid pointer to an initialized executor

◆ rclc_executor_trigger_all()

bool rclc_executor_trigger_all ( const struct rclc_executor_trigger_handle_t *  handles,
size_t  size,
void *  obj 
)

Built-in trigger: fire when ALL handles have data ready.

rclc's rclc_executor_trigger_all. obj is unused.

An EMPTY handle array fires, because "every handle has data" is vacuously true — upstream's loop simply does not execute and returns true. Ours returned false for that case until phase-417 stage 3; it was the same compile-and-differ class as rclc_executor_trigger_one one function over, found by sweeping the siblings rather than by a report.

Safety

  • handles must point to a valid array of at least size elements

◆ rclc_executor_trigger_always()

bool rclc_executor_trigger_always ( const struct rclc_executor_trigger_handle_t *  handles,
size_t  size,
void *  obj 
)

Built-in trigger: always fire (unconditionally).

rclc's rclc_executor_trigger_always.

Safety

  • handles, size and obj are unused

◆ rclc_executor_trigger_any()

bool rclc_executor_trigger_any ( const struct rclc_executor_trigger_handle_t *  handles,
size_t  size,
void *  obj 
)

Built-in trigger: fire when ANY handle has data ready.

rclc's rclc_executor_trigger_any. obj is unused; an empty handle array does not fire.

Safety

  • handles must point to a valid array of at least size elements

◆ rclc_executor_trigger_index()

bool rclc_executor_trigger_index ( const struct rclc_executor_trigger_handle_t *  handles,
size_t  size,
void *  obj 
)

Built-in trigger: fire when the handle at the index stored in obj has data.

OURS, not rclc's — ROS 2 has no counterpart. It is the pre-phase-417 behaviour of rclc_executor_trigger_one, kept under a name that cannot be confused with upstream's entity-pointer contract. Reach for it only when the image genuinely knows its registration order; naming the entity is safer and is what a ported node does.

obj must point to a caller-owned size_t holding the handle index. Passing (void*)(size_t)idx directly is NOT supported — that pattern is UB on strict-alignment targets and CHERI, and the function will dereference the pointer.

static size_t my_trigger_index = 2;
rcl_ret_t rclc_executor_set_trigger(struct rclc_executor_t *executor, rclc_executor_trigger_t trigger, void *context)
bool rclc_executor_trigger_index(const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)

Safety

  • handles must point to a valid array of at least size elements.
  • obj must point to a valid size_t alive for the trigger's lifetime.

◆ rclc_executor_trigger_one()

bool rclc_executor_trigger_one ( const struct rclc_executor_trigger_handle_t *  handles,
size_t  size,
void *  obj 
)

Built-in trigger: fire when the handle registered from the entity obj has data.

rclc's rclc_executor_trigger_one: obj is the ENTITY POINTER, and the predicate walks the handle array looking for a handle that both has data and was registered from that entity.

bool rclc_executor_trigger_one(const struct rclc_executor_trigger_handle_t *handles, size_t size, void *obj)

Until phase-417 stage 3 this function read *(size_t *)obj and used it as an INDEX into the readiness array. The upstream spelling above compiled with no warning and then reinterpreted the entity's address as an index, which is essentially always out of range — so the trigger never fired, the executor dispatched nothing, and nothing said so (RFC-0089: never compile and differ). The index form still exists under its own name, [rclc_executor_trigger_index].

A NULL obj, or an entity this executor never registered, matches nothing and the trigger never fires — upstream's behaviour for an unknown object.

Safety

  • handles must point to a valid array of at least size elements

◆ rclc_executor_wait_for_publishers()

rcl_ret_t rclc_executor_wait_for_publishers ( struct rclc_executor_t *  executor,
const char *  topic_name,
size_t  count,
uint32_t  timeout_ms 
)

phase-444 — block until at least count publishers are visible on topic_name, or timeout_ms elapses. Upstream's rcl_wait_for_publishers.

The startup-ordering primitive one entity kind over from [rclc_client_wait_for_service](crate::service::rclc_client_wait_for_service), and built the same way: a spin on the discovery count, so other subscriptions and timers keep making progress while it waits (RFC-0021 — a blocking helper takes the executor and drives it, which is what makes the timeout reliable on a single-threaded transport).

This is the one BLOCKING member of the graph family, and it does not weaken the family's contract — it composes it. rclc_executor_count_publishers underneath still reports only what has been DISCOVERED and still never blocks; what waits is this loop, by polling it.

A backend that cannot see the graph at all (XRCE) returns RCL_RET_UNSUPPORTED IMMEDIATELY rather than waiting out the budget. That differs deliberately from rclc_client_wait_for_service, which waits and reports RCL_RET_TIMEOUT (issue 1087): for a service probe, not-yet-answerable is a transient; for the graph it is permanent, and spending the budget to say TIMEOUT would report "none appeared" for a backend that cannot see publishers at all — collapsing "cannot tell you" into "not there", which is the distinction RFC-0036 exists to keep.

count == 0 returns RCL_RET_OK immediately without asking the backend: "at least zero" is true of every graph and needs no discovery.

Returns

  • RCL_RET_OK — at least count publishers are visible.
  • RCL_RET_TIMEOUT — timeout_ms elapsed with fewer than count.
  • RCL_RET_UNSUPPORTED — the backend cannot read the graph.
  • RCLC_RET_REENTRANT — called from inside a dispatch.
  • RCL_RET_NOT_INIT — executor not initialised.
  • RCL_RET_INVALID_ARGUMENT — executor or topic_name is null.

Safety

  • executor must point to an initialised executor.
  • topic_name must be a valid NUL-terminated string.

◆ rclc_executor_wait_for_subscribers()

rcl_ret_t rclc_executor_wait_for_subscribers ( struct rclc_executor_t *  executor,
const char *  topic_name,
size_t  count,
uint32_t  timeout_ms 
)

phase-444 — block until at least count subscribers are visible on topic_name. Upstream's rcl_wait_for_subscribers. See rclc_executor_wait_for_publishers for the contract, the return codes, and why a backend with no graph answers immediately.

Safety

  • executor must point to an initialised executor.
  • topic_name must be a valid NUL-terminated string.

◆ rclc_get_fully_qualified_name()

rcl_ret_t rclc_get_fully_qualified_name ( const char *  node_name,
const char *  node_namespace,
char *  buf,
size_t  buf_len,
size_t *  out_len 
)

Join a node name and namespace into a fully-qualified name.

/robot + talker -> /robot/talker. The root namespace collapses, so / + talker is /talker and never //talker, and a namespace given without a leading / is absolutised.

Why this exists, and why it takes two strings rather than a handle

rclc_executor_get_node_names hands a visitor the name and namespace of a DISCOVERED node as two borrowed strings; this is the step that makes them one. ROS 2 has no counterpart: rcl_get_node_names returns two parallel arrays and leaves the correlation and the join to the caller, and rcl_node_get_fully_qualified_name answers only for the caller's OWN node (that one is [rclc_node_get_fully_qualified_name]). rclcpp is the only upstream layer that joins for you, and it is not available in C.

Parameters

  • node_name - the bare node name, null-terminated
  • node_namespace - the namespace, null-terminated; "" and "/" are root
  • buf - destination for the null-terminated result
  • buf_len - capacity of buf, INCLUDING the terminator
  • out_len - receives the length written, excluding the terminator. On RCLC_RET_FULL it receives the length that WOULD be written, so a caller can size a second attempt.

Returns

  • RCL_RET_OK
  • RCL_RET_INVALID_ARGUMENT — a NULL pointer, a non-UTF-8 input, or a name so long the join cannot be represented
  • RCLC_RET_FULL — buf_len is too small; out_len says what is needed. FULL and not BUFFER_TOO_SMALL because rcl_ret_t has no such code: that one exists on the RMW ABI (nros_rmw_ret_t). It was CITED by a doc comment on rclc_publisher_publish_streamed, which returns RCLC_RET_PUBLISH_FAILED instead — corrected under issue 1126, so this is now the only place the two ABIs' spellings are contrasted. Naming a constant the header does not define would have made that two wrong references rather than one.

Safety

  • node_name and node_namespace must be valid null-terminated strings
  • buf must be writable for buf_len bytes; out_len must be valid or NULL

◆ rclc_get_ros_time_override()

rcl_ret_t rclc_get_ros_time_override ( const struct rcl_clock_t *  clock,
int64_t *  nanoseconds 
)

Read the ROS time override back, in nanoseconds since the epoch.

The C face of nros_core::Clock::get_ros_time_override, whose Option this splits into a status and an out-parameter: RCL_RET_OK and a value when an override is in effect, RCLC_RET_NOT_FOUND and an untouched out-parameter when none is. rcl has no equivalent — a caller there reads the clock — but dropping it would leave the C mirror of the Rust surface one entry point short, and "is a simulator driving me, and at what time" is one question.

◆ rclc_get_zero_initialized_polling_action_client()

struct rclc_polling_action_client_t rclc_get_zero_initialized_polling_action_client ( void  )

Get a zero-initialized polling action client.

◆ rclc_get_zero_initialized_polling_action_server()

struct rclc_polling_action_server_t rclc_get_zero_initialized_polling_action_server ( void  )

Get a zero-initialized polling action server.

◆ rclc_get_zero_initialized_polling_client()

struct rclc_polling_client_t rclc_get_zero_initialized_polling_client ( void  )

Get a zero-initialized polling service client.

◆ rclc_get_zero_initialized_polling_service()

struct rclc_polling_service_t rclc_get_zero_initialized_polling_service ( void  )

Get a zero-initialized polling service server.

◆ rclc_get_zero_initialized_polling_subscription()

struct rclc_polling_subscription_t rclc_get_zero_initialized_polling_subscription ( void  )

Get a zero-initialized polling subscription.

◆ rclc_goal_status_to_string()

const char * rclc_goal_status_to_string ( enum rclc_goal_status_t  status)

Get status name as string.

◆ rclc_goal_uuid_equal()

bool rclc_goal_uuid_equal ( const struct rclc_goal_uuid_t *  a,
const struct rclc_goal_uuid_t *  b 
)

Compare two goal UUIDs.

◆ rclc_goal_uuid_generate()

rcl_ret_t rclc_goal_uuid_generate ( struct rclc_goal_uuid_t *  uuid)

Generate a new random goal UUID.

◆ rclc_guard_condition_clear()

rcl_ret_t rclc_guard_condition_clear ( struct rcl_guard_condition_t *  guard)

Clear the triggered flag without dispatching — the other half of [rclc_guard_condition_is_triggered], for a polling owner that handled the event itself. Reads the same arena flag, for the same reason.

◆ rclc_guard_condition_is_triggered()

bool rclc_guard_condition_is_triggered ( const struct rcl_guard_condition_t *  guard)

Is this guard condition triggered and not yet dispatched?

The RFC-0022 POLLING tier: a task that owns its own loop and never calls a callback still needs to see the flag another thread or an ISR set. rcl has no such reader, so this is ours.

It reads the ARENA flag, which is the one rclc_guard_condition_trigger writes — and it had to, from the moment creation became registration. The local triggered byte this used to read was only ever written by the fallback path of an UNREGISTERED guard, so with the retirement of nros_guard_condition_init it would have answered false for every guard condition that exists: a reader that compiles, runs, and is always wrong. The executor CONSUMES the flag when it dispatches, so this answers "set and not yet dispatched"; a caller that both polls this and spins the executor is racing itself.

◆ rclc_guard_condition_is_valid()

bool rclc_guard_condition_is_valid ( const struct rcl_guard_condition_t *  guard)

Check if guard condition is valid (initialized).

◆ rclc_guard_condition_trigger()

rcl_ret_t rclc_guard_condition_trigger ( struct rcl_guard_condition_t *  guard)

Trigger a guard condition — thread-safe and lock-free.

Stores into the atomic flag the executor's arena holds for this guard and then fires the runtime wake hook, so an ISR or a foreign task releases a spin_once already blocked in drive_io rather than waiting out its poll timeout. The callback runs on the executor's thread, at its next spin.

This is nros_generated.h's nros_<entity>_<verb> spelling, and until 2026-09-18 it DID NOT EXIST — only rcl's verb-first [rcl_trigger_guard_condition] did, while the ledger, this crate's own docs and the custom-platform example's README all named this one. The example's README told a reader to call a symbol nothing defined.

Safety

◆ rclc_has_custom_transport()

rcl_ret_t rclc_has_custom_transport ( void  )

Phase 115.C — query whether a custom transport is currently registered. Returns 1 if a transport is registered, 0 otherwise. Useful for board crates that want to fall back to a static transport when no runtime override has been provided.

◆ rclc_heap_peak_bytes()

size_t rclc_heap_peak_bytes ( void  )

Peak outstanding bytes through the Rust global allocator since boot.

◆ rclc_heap_platform_used_bytes()

size_t rclc_heap_platform_used_bytes ( void  )

Bytes currently outstanding from the platform's unified heap — the true figure spanning both the Rust global allocator and the C side (zenoh-pico etc.), where the port owns one shared kernel heap. 0 if the port does not instrument heap usage.

◆ rclc_heap_total_bytes()

size_t rclc_heap_total_bytes ( void  )

Total managed heap size in bytes (used + free) reported by the platform, or 0 if unknown.

◆ rclc_heap_used_bytes()

size_t rclc_heap_used_bytes ( void  )

Bytes currently outstanding through the Rust global allocator.

◆ rclc_lifecycle_fini()

rcl_ret_t rclc_lifecycle_fini ( struct rcl_lifecycle_state_machine_t *  sm)

Finalize a lifecycle state machine.

◆ rclc_lifecycle_get_current_state()

uint8_t rclc_lifecycle_get_current_state ( const struct rcl_lifecycle_state_machine_t *  sm)

Get the current lifecycle state.

◆ rclc_lifecycle_get_zero_initialized()

struct rcl_lifecycle_state_machine_t rclc_lifecycle_get_zero_initialized ( void  )

Get a zero-initialized lifecycle state machine.

◆ rclc_lifecycle_init()

rcl_ret_t rclc_lifecycle_init ( struct rcl_lifecycle_state_machine_t *  sm)

Initialize a standalone lifecycle state machine.

The machine starts in Unconfigured with no callbacks registered. It is self-contained: it drives the REP-2002 transition table and the six transition callbacks, and it is NOT bound to a node and registers no ROS 2 services. A node that should answer ros2 lifecycle set|get|list uses the executor-scoped family instead — rclc_executor_register_lifecycle_services plus nros_executor_lifecycle_*.

Issue 0792: this took a const rcl_node_t *node until it was noticed that the pointer was only NULL-checked and never stored. The parameter is gone rather than stored, because storing it would not have helped: the executor-scoped family does not reach its node through an rcl_node_t at all. Executor::register_lifecycle_services builds the five servers on the executor's own session, keeps them in the executor's LifecycleRuntimeState, and relies on the executor's spin loop to poll them — none of which a caller-held rcl_lifecycle_state_machine_t has access to or can be given by a node pointer. The removed nros_make_node_a_lifecycle_node alias went with it for the same reason: it could not do what its name said.

◆ rclc_lifecycle_register_on_error()

rcl_ret_t rclc_lifecycle_register_on_error ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the error transition (error recovery).

◆ rclc_lifecycle_register_on_shutdown()

rcl_ret_t rclc_lifecycle_register_on_shutdown ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the shutdown transition.

◆ rclc_lifecycle_state_label()

const char * rclc_lifecycle_state_label ( uint8_t  state_id)

The lifecycle_msgs/msg/State.label for state_id, or NULL for an id that is not a lifecycle state. See [rclc_lifecycle_transition_label].

◆ rclc_lifecycle_state_machine_change_state()

rcl_ret_t rclc_lifecycle_state_machine_change_state ( struct rcl_lifecycle_state_machine_t *  sm,
uint8_t  transition_id 
)

Trigger a lifecycle state transition.

◆ rclc_lifecycle_state_machine_register_on_activate()

rcl_ret_t rclc_lifecycle_state_machine_register_on_activate ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the activate transition.

◆ rclc_lifecycle_state_machine_register_on_cleanup()

rcl_ret_t rclc_lifecycle_state_machine_register_on_cleanup ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the cleanup transition.

◆ rclc_lifecycle_state_machine_register_on_configure()

rcl_ret_t rclc_lifecycle_state_machine_register_on_configure ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the configure transition.

◆ rclc_lifecycle_state_machine_register_on_deactivate()

rcl_ret_t rclc_lifecycle_state_machine_register_on_deactivate ( struct rcl_lifecycle_state_machine_t *  sm,
rclc_lifecycle_callback_t  cb,
void *  context 
)

Register a callback for the deactivate transition.

◆ rclc_lifecycle_transition_goal_state()

uint8_t rclc_lifecycle_transition_goal_state ( uint8_t  transition_id)

The state transition_id ADVERTISES as its destination — rclcpp's Transition::goal_state().

This is where a SUCCEEDING callback lands. A failing one rolls back or routes to ErrorProcessing, which is a runtime outcome and not a property of the graph. Returns 0 for an unimplemented id.

◆ rclc_lifecycle_transition_graph()

rcl_ret_t rclc_lifecycle_transition_graph ( const uint8_t **  out_ids,
size_t *  out_count 
)

The whole REP-2002 transition graph: every transition id, in lifecycle_msgs order.

out_ids receives a pointer to a STATIC array of *out_count ids — no allocation, no caller buffer, and nothing to free. Pair each id with [rclc_lifecycle_transition_label], [rclc_lifecycle_transition_start_state] and [rclc_lifecycle_transition_goal_state] to get the row rclcpp's Transition object carries.

This is the SAME table ~/get_transition_graph serves, so a node and a remote ros2 lifecycle list cannot disagree about it.

Safety

out_ids and out_count must be valid, writable pointers.

◆ rclc_lifecycle_transition_label()

const char * rclc_lifecycle_transition_label ( uint8_t  transition_id)

The lifecycle_msgs/msg/Transition.label for transition_id, or NULL when the id is not one nano-ros implements.

The returned pointer is a NUL-terminated string literal with STATIC lifetime — the caller neither owns nor frees it, and there is no capacity argument, because unlike a parameter description this text is ours and its length is known at compile time.

◆ rclc_lifecycle_transition_start_state()

uint8_t rclc_lifecycle_transition_start_state ( uint8_t  transition_id)

The state transition_id may be taken FROM — rclcpp's Transition::start_state(), spelled source_state in Rust.

Returns 0, which is no lifecycle state, for an unimplemented id.

◆ rclc_monitors_arm()

void rclc_monitors_arm ( void  )

phase-474 I2 – the application's start-up is over: arm the contract monitors of every executor that waits for this (CONFIG_NROS_MONITOR_ARM_ON_CALL). Call it where the application enters its running state, for example an INIT/RUN state machine's RUN transition.

Safe from any thread and from inside a callback: it bumps one atomic, and each executor arms at its next spin. Before arming, a monitor verdict is counted (suppressed_before_arm) but not stored, logged or traced. On an image whose monitors arm at the first spin (the default) it does nothing. No-op in a build without an RMW, which has no monitors.

◆ rclc_node_create_guard_condition()

rcl_ret_t rclc_node_create_guard_condition ( struct rcl_node_t *  node,
struct rcl_guard_condition_t *  out,
rclc_guard_condition_callback_t  callback,
void *  context 
)

Create a guard condition on node — the ONE creation shape (phase-417 W4.e, RFC-0089 stage 4).

A guard condition is the cross-thread / ISR wake source: any thread may call [rclc_guard_condition_trigger] and callback runs on the executor's next spin. The flag lives in the executor's arena, so creation has to reach an executor — and the thing a caller has in hand is a NODE, which is why the node is the owner in all three of our languages. callback may be NULL for a wake with no work attached; context is handed back to it unchanged.

This replaced three calls, and until 2026-09-18 the first two produced an INERT object. nros_guard_condition_init(guard, support) only zeroed fields — nothing reached the arena until nros_executor_add_guard_condition ran, so between the two the handle read handle_id == SIZE_MAX and a trigger fell back to a local flag no executor watches. Binding the callback after the fact was also the shape we already REFUSE in C++ at GuardCondition::set_on_trigger_callback, so one constraint was enforced in two languages and contradicted in the third. All three names are retired with no forwarder (stage 6 step B): the whole in-tree cost was one example.

Ordering

node must be bound to an executor through rclc_executor_node_init — the executor exists first, then the node. A node from the legacy rclc_node_init_default path reaches no executor and gets RCL_RET_NOT_INIT, which is what rclc_node_resolve_name answers for the same reason: the capability is UNREACHABLE from that node, not absent.

Returns

  • RCL_RET_OK — created, registered, and the callback is bound.
  • RCL_RET_INVALID_ARGUMENT — node or out is NULL.
  • RCL_RET_NOT_INIT — the node is uninitialised, is not bound to an executor, or that executor has been finalised.
  • RCLC_RET_BAD_SEQUENCE — out is not zero-initialised (a double create).
  • RCLC_RET_FULL — the executor's handle table is full.

Safety

  • node must point to a valid, executor-bound rcl_node_t.
  • out must point to writable storage that outlives the executor — registration is one-way and the arena records the entity pointer.

◆ rclc_node_get_fully_qualified_name()

rcl_ret_t rclc_node_get_fully_qualified_name ( const struct rcl_node_t *  node,
char *  buf,
size_t  buf_len,
size_t *  out_len 
)

This node's fully-qualified name — rcl_node_get_fully_qualified_name.

A buffer rather than upstream's const char *, and the difference is not cosmetic: rcl can hand back a pointer because it STORES the joined string, and storing it here would cost up to MAX_NAME_LEN + MAX_NAMESPACE_LEN bytes per node on a target that counts them, to cache something two strings already hold. Same shape as [rclc_get_fully_qualified_name], which is the other half of this pair.

Returns

As [rclc_get_fully_qualified_name], plus RCL_RET_NOT_INIT when the node is not initialised.

The composition is NOT written here. It is nros_node::names:: fully_qualified_name, which is expand_name with the private-name source ~ — the same seam every entity name on this node goes through (Executor::resolve_entity_name_for), so a node's FQN and its entities' FQNs can never disagree about namespace normalisation. A second ‘push(namespace); push(’/'); push(name)` in the C layer is exactly RFC-0020's violation class 4, name construction in a wrapper, and it is what the four sibling implementations of this already spelled differently.

Safety

  • node must be a valid pointer to an initialised node
  • buf must be writable for buf_len bytes; out_len must be valid or NULL

◆ rclc_node_get_graph_guard_condition()

rcl_ret_t rclc_node_get_graph_guard_condition ( struct rcl_node_t *  node,
struct rcl_guard_condition_t *  out,
rclc_guard_condition_callback_t  callback,
void *  context 
)

Upstream rcl_node_get_graph_guard_condition — a guard condition the BACKEND triggers when the ROS graph changes (phase-467 Row 8).

Upstream's NAME over [rclc_node_create_guard_condition]'s SHAPE, and that envelope is stated rather than silent. rcl_node_get_graph_guard_ condition(node) RETURNS a borrowed pointer to a guard the node already owns, and the only documented thing to do with it is rcl_wait_set_add_guard_condition. Two constraints rule that out here: RFC-0018/0019 forbids returning an owned handle across this seam (every entity is created into caller storage, status in the return), and we decline wait sets entirely (RFC-0002 — one executor per RTOS task). So this CREATES a guard condition into out with callback bound at creation, exactly like its sibling, and differs from it only in who pulls the trigger: there the application, here the backend's discovery path. A ported file that tries to put the handle in a wait set fails at the wait set, not at this name.

The callback is an EDGE and carries nothing. "What changed" is answered by re-reading the graph (nros_node_get_names, nros_count_publishers, …); delivering a diff would mean buffering the graph, which is the cache a small target cannot afford, and the ABI slot has said so since phase-376 W4.

Ordering

As [rclc_node_create_guard_condition]: node must be bound to an executor through rclc_executor_node_init.

Returns

  • RCL_RET_OK — created, registered, and the backend will trigger it.
  • RCL_RET_UNSUPPORTED — this backend has no graph (XRCE, uORB), asked BEFORE anything is consumed, so out is untouched and no handle slot is spent. Never OK with a guard nothing fires: that silent difference is what RFC-0089 Part I refuses.
  • RCL_RET_INVALID_ARGUMENT — node or out is NULL.
  • RCL_RET_NOT_INIT — the node is uninitialised, is not bound to an executor, or that executor has been finalised.
  • RCLC_RET_BAD_SEQUENCE — out is not zero-initialised.
  • RCLC_RET_FULL — the executor's handle table is full.

Safety

  • node must point to a valid, executor-bound rcl_node_t.
  • out must point to writable storage that outlives the executor.

Note what out is NOT: the backend never receives a pointer to it. The executor keeps its own handle to the same arena flag and retires it from the backend before freeing it, so a caller that frees or reuses this struct cannot leave the backend calling into dead storage — issue 1385's hazard, designed out rather than fixed afterwards.

◆ rclc_node_get_logger()

const void * rclc_node_get_logger ( const struct rcl_node_t *  node)

Phase 88.12 — return the nros::Logger keyed on this node's name.

The returned handle is opaque from the C side; pass it to nros_log_info(...) / nros_log_warn(...) / etc. (declared in <rclc/log.h>). The lifetime is 'static — loggers live for the process; callers must NOT free the returned pointer.

Parameters

  • node - Pointer to an initialized node.

Returns

  • Opaque rclc_logger_t * (= &'static nros_log::Logger), or NULL if node is NULL / uninitialised.

Safety

  • node must be a valid pointer.

◆ rclc_node_get_serialization_format()

const char * rclc_node_get_serialization_format ( const struct rcl_node_t *  node)

RFC-0088 D4 / phase-421 W2 — the serialization format the backend behind THIS node speaks, as its cross-image identity string ("cdr", "uorb").

Resolved through the node's own session, not from an image-wide constant. That distinction is the whole point: a single-backend image could answer from the generated NROS_SERIALIZATION_FORMAT macro, but a bridge image links two backends and has no single answer — its two nodes sit on two sessions and this function reports each one's format separately. The macro is the fast path for the common case; this is the correct one always.

Parameters

  • node - Pointer to an initialized node

Returns

  • Pointer to a static, null-terminated format name; the caller must not free it and it stays valid for the life of the image.
  • NULL if node is NULL / uninitialised, if its session cannot be resolved, or if the backend does not declare a format. NULL is not a synonym for "cdr" — a backend that has not said what it speaks has not said CDR, and guessing on its behalf is exactly the fallback the vtable's sibling identity slot spent two phases wrongly promising.

Safety

  • node must be a valid pointer

◆ rclc_node_init_default()

rcl_ret_t rclc_node_init_default ( struct rcl_node_t *  node,
const char *  name,
const char *  namespace_,
const struct rclc_support_t *  support 
)

Initialize a node with default options — rclc's rclc_node_init_default, in rclc's argument ORDER.

The parameters were REORDERED at phase-417 stage 6. This is the one entry point in the whole C surface that is a pure PERMUTATION of its upstream counterpart (measured over the surface, not assumed):

rclc rclc_node_init_default(node, name, namespace_, support)
was nros_node_init (node, support, name, namespace_)

The rename and the reorder land TOGETHER, and that is not stylistic. RFC-0089's corrected hazard note: in C an incompatible pointer argument is a WARNING, not an error, even under -Wall -Wextra, so a reorder alone is silent-by-default for out-of-tree callers who do not build with our flags. Renaming makes a stale call fail on the IDENTIFIER, which C does diagnose fatally, and that is the whole guard now: phase-417 stage 6 step B retired the nros_node_init forwarder, so the old identifier resolves to nothing. While it existed it was a static inline naming each parameter and never a macro, because a macro would have forwarded positionally and silently built a node with its name in the support slot.

Equivalent to building a [rcl_node_options_t] via [rcl_node_get_default_options], copying namespace_ into its namespace field, and calling [rclc_node_init_ex] — which is rcl_node_init_with_options's counterpart and keeps OUR order, because it has no rclc counterpart to match.

Parameters

  • node - Pointer to a zero-initialized node
  • name - Node name (null-terminated string)
  • namespace_ - Node namespace (null-terminated string, use "/" for root)
  • support - Pointer to an initialized support context

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or strings are invalid
  • RCL_RET_NOT_INIT if support is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All pointers must be valid
  • name and namespace_ must be valid null-terminated strings

◆ rclc_node_init_ex()

rcl_ret_t rclc_node_init_ex ( struct rcl_node_t *  node,
const struct rclc_support_t *  support,
const char *  name,
const struct rcl_node_options_t *  options 
)

Phase 104.C.8 — initialize a Node with extended options.

Thin C wrapper over the Rust Executor::node_builder(name).rmw(...) .locator(...).domain_id(...).namespace(...).sched(...).build() chain. Options fields with *_len == 0 (or domain_id_override == NROS_DOMAIN_ID_INHERIT) inherit from the support context, matching the legacy single-Node behaviour rclc_node_init_default provides.

The rmw_name selector drives Phase 104 multi-RMW Node binding: a bridge node can be initialised with options.rmw_name = "cyclonedds" while the support context's primary backend is "zenoh", and subsequent publishers/subscribers created via this Node route through the named backend's session. (Internal multi-Session dispatch piggy-backs on the executor's extra_sessions cache; see Phase 104.C.3.)

Currently the inline node_id slot stays 0; per-Node multi-RMW dispatch in C lands once the C executor surfaces Executor::node_builder (Phase 104.C.8 follow-up). Options fields round-trip into the node struct today so users can write code against the final API surface without waiting for that follow-up.

Parameters

  • node - Pointer to a zero-initialized node
  • support - Pointer to an initialized support context
  • name - Node name (null-terminated string)
  • options - Pointer to an [rcl_node_options_t] (must be non-NULL)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT on NULL / invalid strings / overrun buffers
  • RCLC_RET_BAD_SEQUENCE if the node is already initialized
  • RCL_RET_NOT_INIT if support is not initialized

Safety

  • All pointers must be valid
  • name must be a valid NUL-terminated UTF-8 string
  • options fields must satisfy their declared length invariants

◆ rclc_node_resolve_name()

rcl_ret_t rclc_node_resolve_name ( const struct rcl_node_t *  node,
const char *  input_name,
bool  only_expand,
char *  output_name,
size_t  output_size 
)

Expand input_name against this node's namespace and apply its remap rules — what a topic or service name a caller builds at runtime will actually become on the wire.

rcl's rcl_node_resolve_name without its allocator: the caller supplies the output buffer, hence the distinct rclc_ name (phase-492 W1.b). Gap c:node_resolve_name records the reason it was missing: our names are resolved at codegen/launch time (RFC-0046), so a C caller constructing one dynamically had no way to ask.

Forwards to Executor::resolve_entity_name_for — the identical call the registration paths in executor.rs make for every publisher, subscription, service and action. That is the point: this answers what creating the entity WOULD do, not what a parallel implementation thinks it would do.

only_expand is rcl's own parameter and carries rcl's meaning: true applies ROS 2 name expansion (~, relative → FQN) and ignores remap rules; false also applies them.

Remaps live on the executor, so only_expand == false needs an executor-bound node (rclc_executor_node_init). On the legacy rclc_node_init_default path this returns RCL_RET_NOT_INIT rather than quietly expanding without the rules — silently dropping a routing rule is the failure this whole campaign exists to stop, and the caller who wants expansion alone can ask for it by passing true.

Divergences from rcl, both forced: no rcl_allocator_t (we have no allocator, so the caller owns the buffer and RCLC_RET_FULL reports a short one), and no is_service (it selects between rcl's topic- and service-name VALIDATORS, which we do not ship; taking the argument and ignoring it would be the inert-parameter defect RFC-0089 §"The hazard" names).

Safety

  • node must be NULL or point to a valid rcl_node_t.
  • input_name must be NULL or a valid NUL-terminated C string.
  • output_name must be NULL or writable for output_size bytes.

◆ rclc_node_set_qos_overrides()

rcl_ret_t rclc_node_set_qos_overrides ( struct rcl_node_t *  node,
const struct rclc_qos_override_t *  overrides,
size_t  len 
)

Install the per-topic QoS override table the deploy plan lowered from qos_overrides.<topic>.<role>.<policy> launch params (issue #52). Every entity created on node afterwards folds the matching (topic, role) entries into its QoS before the backend-compat check — the C/C++ mirror of Rust's NodeHandle::set_qos_overrides. Call once, after rclc_node_init_default* and before creating publishers/subscriptions (a generated entry does this before configure(node)).

overrides must outlive the node (a static array in the generated entry). Pass len == 0 (or a null overrides) to clear.

Safety

  • node must point to an initialised rcl_node_t.
  • overrides must be null or point to len valid rclc_qos_override_t (each topic a valid NUL-terminated UTF-8 C string), living at least as long as the node.

◆ rclc_polling_action_client_fini()

rcl_ret_t rclc_polling_action_client_fini ( struct rclc_polling_action_client_t *  client)

Finalize a polled action client: drops the inline core, which closes its channels.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if client is NULL
  • RCL_RET_NOT_INIT if it is not initialised
  • RCLC_RET_STALE_NODE if its node has already been finalised (issue 1386)

Safety

client must be a valid pointer.

◆ rclc_polling_action_client_init()

rcl_ret_t rclc_polling_action_client_init ( struct rclc_polling_action_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_action_type_t *  type_info,
const char *  action_name 
)

Phase 122.3.c.6.b — initialize an L1 polling-mode action client.

Creates the 4 transport channels (3 service clients + feedback subscriber) immediately and stores the ActionClientCore inline in the rclc_polling_action_client_t. The caller drives the goal lifecycle via:

  • rclc_polling_action_client_send_goal_raw — start a new goal; returns the generated 16-byte UUID.
  • rclc_polling_action_client_try_recv_goal_response_raw — poll for the send_goal RPC reply (accepted / rejected).
  • rclc_polling_action_client_send_get_result_request_raw + _try_recv_result_raw — fetch the terminal result.
  • rclc_polling_action_client_send_cancel_request_raw + _try_recv_cancel_response_raw — cancel a goal.
  • rclc_polling_action_client_try_recv_feedback_raw — drain feedback.

Safety

All pointers must be valid; action_name must be a valid null-terminated string.

◆ rclc_polling_action_client_send_cancel_request_raw()

rcl_ret_t rclc_polling_action_client_send_cancel_request_raw ( struct rclc_polling_action_client_t *  client,
const uint8_t(*)  goal_id[16] 
)

Phase 122.3.c.6.b — L1 polling: send a cancel request.

◆ rclc_polling_action_client_send_get_result_request_raw()

rcl_ret_t rclc_polling_action_client_send_get_result_request_raw ( struct rclc_polling_action_client_t *  client,
const uint8_t(*)  goal_id[16] 
)

Phase 122.3.c.6.b — L1 polling: send a get_result request for the given goal. Reply lands via _try_recv_result_raw.

◆ rclc_polling_action_client_send_goal_raw()

rcl_ret_t rclc_polling_action_client_send_goal_raw ( struct rclc_polling_action_client_t *  client,
const uint8_t *  goal_cdr,
size_t  goal_len,
uint8_t(*)  goal_id_out[16] 
)

Phase 122.3.c.6.b — L1 polling: send a goal. Writes the generated 16-byte UUID into goal_id_out. Poll for the accept/reject reply via rclc_polling_action_client_try_recv_goal_response_raw.

◆ rclc_polling_action_client_set_cancel_response_wake_callback()

rcl_ret_t rclc_polling_action_client_set_cancel_response_wake_callback ( struct rclc_polling_action_client_t *  client,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — wake on the cancel-reply channel.

◆ rclc_polling_action_client_set_feedback_wake_callback()

rcl_ret_t rclc_polling_action_client_set_feedback_wake_callback ( struct rclc_polling_action_client_t *  client,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — wake on the feedback channel.

◆ rclc_polling_action_client_set_goal_response_wake_callback()

rcl_ret_t rclc_polling_action_client_set_goal_response_wake_callback ( struct rclc_polling_action_client_t *  client,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on the send_goal-reply channel of an L1 polling-mode action client.

◆ rclc_polling_action_client_set_result_wake_callback()

rcl_ret_t rclc_polling_action_client_set_result_wake_callback ( struct rclc_polling_action_client_t *  client,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — wake on the get_result-reply channel.

◆ rclc_polling_action_client_try_recv_cancel_response_raw()

int32_t rclc_polling_action_client_try_recv_cancel_response_raw ( struct rclc_polling_action_client_t *  client,
uint8_t *  buf,
size_t  buf_len 
)

Phase 122.3.c.6.c — L1 polling: try to receive the cancel-RPC reply. Returns 0 when no reply yet, >0 bytes copied into buf, negative on error.

◆ rclc_polling_action_client_try_recv_feedback_raw()

int32_t rclc_polling_action_client_try_recv_feedback_raw ( struct rclc_polling_action_client_t *  client,
uint8_t *  buf,
size_t  buf_len,
uint8_t(*)  goal_id_out[16] 
)

Phase 122.3.c.6.b — L1 polling: try to receive feedback for any goal. Returns 0 when no feedback yet, >0 bytes copied (with goal_id_out filled), negative on error.

◆ rclc_polling_action_client_try_recv_goal_response_raw()

int32_t rclc_polling_action_client_try_recv_goal_response_raw ( struct rclc_polling_action_client_t *  client,
uint8_t *  buf,
size_t  buf_len 
)

Phase 122.3.c.6.b — L1 polling: try to receive a send_goal reply (the accept/reject response). Returns 0 when no reply yet, >0 bytes when one was copied into buf, negative on error.

◆ rclc_polling_action_client_try_recv_result_raw()

int32_t rclc_polling_action_client_try_recv_result_raw ( struct rclc_polling_action_client_t *  client,
uint8_t *  buf,
size_t  buf_len 
)

Phase 122.3.c.6.b — L1 polling: try to receive a get_result reply. Returns 0 when no reply yet, >0 bytes copied, negative on error.

◆ rclc_polling_action_server_accept_goal_raw()

rcl_ret_t rclc_polling_action_server_accept_goal_raw ( struct rclc_polling_action_server_t *  server,
const uint8_t(*)  goal_id[16],
int64_t  sequence_number 
)

Phase 122.3.c.6.b — L1 polling: accept a goal received via try_recv_goal_request_raw.

◆ rclc_polling_action_server_complete_goal_raw()

rcl_ret_t rclc_polling_action_server_complete_goal_raw ( struct rclc_polling_action_server_t *  server,
const uint8_t(*)  goal_id[16],
enum rclc_goal_status_t  status,
const uint8_t *  result_cdr,
size_t  result_len 
)

Phase 122.3.c.6.b — L1 polling: mark a goal terminal.

status must be one of SUCCEEDED / ABORTED / CANCELED. result_cdr is the CDR-encoded <Action>_Result_ payload (the core handles the status wrapper before storing in the slab).

◆ rclc_polling_action_server_expire_goals()

rcl_ret_t rclc_polling_action_server_expire_goals ( struct rclc_polling_action_server_t *  server,
size_t *  num_expired 
)

The polled twin of [rclc_action_expire_goals].

Safety

server and num_expired must be valid pointers.

◆ rclc_polling_action_server_fini()

rcl_ret_t rclc_polling_action_server_fini ( struct rclc_polling_action_server_t *  server)

Finalize a polled action server: drops the inline core, which closes its five channels.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if server is NULL
  • RCL_RET_NOT_INIT if it is not initialised
  • RCLC_RET_STALE_NODE if its node has already been finalised (issue 1386)

Safety

server must be a valid pointer.

◆ rclc_polling_action_server_get_active_goal_count()

rcl_ret_t rclc_polling_action_server_get_active_goal_count ( struct rclc_polling_action_server_t *  server,
size_t *  out 
)

The polled twin of [rclc_action_server_get_active_goal_count].

Returns

RCL_RET_OK with *out written, RCL_RET_INVALID_ARGUMENT for a NULL argument, RCL_RET_NOT_INIT when the server is not initialised.

Safety

server and out must be valid pointers.

◆ rclc_polling_action_server_goal_exists()

bool rclc_polling_action_server_goal_exists ( struct rclc_polling_action_server_t *  server,
const struct rclc_goal_handle_t *  goal 
)

The polled twin of [rclc_action_server_goal_exists].

Safety

server and goal must be NULL or valid pointers.

◆ rclc_polling_action_server_init()

rcl_ret_t rclc_polling_action_server_init ( struct rclc_polling_action_server_t *  server,
const struct rcl_node_t *  node,
const struct rclc_action_type_t *  type_info,
const char *  action_name 
)

Phase 122.3.c.6.b — initialize an L1 polling-mode action server.

Creates the 5 transport channels immediately and stores the ActionServerCore inline in the rclc_polling_action_server_t. The caller drives the goal lifecycle via:

  • rclc_polling_action_server_try_recv_goal_request_raw — poll for new goal requests (returns goal_id + sequence + payload).
  • rclc_polling_action_server_accept_goal_raw / _reject_goal_raw — reply to the send_goal RPC.
  • rclc_polling_action_server_publish_feedback_raw — push feedback.
  • rclc_polling_action_server_complete_goal_raw — terminate (SUCCEEDED / ABORTED / CANCELED).
  • nros_polling_action_server_try_handle_cancel_raw / _try_handle_get_result_raw — service cancel / get_result RPCs.

Safety

All pointers must be valid; action_name must be a valid null-terminated string.

◆ rclc_polling_action_server_publish_feedback_raw()

rcl_ret_t rclc_polling_action_server_publish_feedback_raw ( struct rclc_polling_action_server_t *  server,
const uint8_t(*)  goal_id[16],
const uint8_t *  feedback_cdr,
size_t  feedback_len 
)

Phase 122.3.c.6.b — L1 polling: publish a feedback message.

feedback_cdr is the CDR-encoded <Action>_Feedback_ payload (without the goal_id prefix — the core wraps it).

◆ rclc_polling_action_server_reject_goal_raw()

rcl_ret_t rclc_polling_action_server_reject_goal_raw ( struct rclc_polling_action_server_t *  server,
int64_t  sequence_number 
)

Phase 122.3.c.6.b — L1 polling: reject a goal received via try_recv_goal_request_raw.

◆ rclc_polling_action_server_send_cancel_reply_raw()

rcl_ret_t rclc_polling_action_server_send_cancel_reply_raw ( struct rclc_polling_action_server_t *  server,
int64_t  sequence_number,
enum rclc_cancel_return_code_t  return_code,
const uint8_t(*)  accepted[16],
size_t  accepted_count 
)

Phase 122.3.c.6.d — L1 polling: reply to a cancel-goal request previously peeked via _try_recv_cancel_request_raw. accepted points to accepted_count goal-ID byte arrays that will transition to CANCELING. Pass an empty list (accepted=NULL, accepted_count=0) with return_code=RCLC_CANCEL_RC_REJECTED to refuse the request entirely.

◆ rclc_polling_action_server_set_cancel_wake_callback()

rcl_ret_t rclc_polling_action_server_set_cancel_wake_callback ( struct rclc_polling_action_server_t *  server,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on the cancel_goal channel of an L1 polling-mode action server. The primary use case from the .c.6.e design discussion — RTOS / event-driven cancel handling.

◆ rclc_polling_action_server_set_get_result_wake_callback()

rcl_ret_t rclc_polling_action_server_set_get_result_wake_callback ( struct rclc_polling_action_server_t *  server,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on the get_result channel of an L1 polling-mode action server.

◆ rclc_polling_action_server_set_goal_wake_callback()

rcl_ret_t rclc_polling_action_server_set_goal_wake_callback ( struct rclc_polling_action_server_t *  server,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on the send_goal channel of an L1 polling-mode action server. state is a caller-owned rclc_wake_state_t that must outlive the server and not move.

◆ rclc_polling_action_server_try_handle_get_result_raw()

int32_t rclc_polling_action_server_try_handle_get_result_raw ( struct rclc_polling_action_server_t *  server,
const uint8_t *  default_result_cdr,
size_t  default_result_len 
)

Phase 122.3.c.6.b — L1 polling: serve a pending get_result query.

default_result_cdr is the default serialized result (without status byte / CDR header) returned to the client when no complete_goal_raw has been called for the queried goal yet.

Returns 0 when no query is pending; 1 when one was served; negative rcl_ret_t on error.

◆ rclc_polling_action_server_try_recv_cancel_request_raw()

int32_t rclc_polling_action_server_try_recv_cancel_request_raw ( struct rclc_polling_action_server_t *  server,
uint8_t(*)  goal_id_out[16],
int64_t *  sequence_number_out,
enum rclc_goal_status_t *  current_status_out 
)

Phase 122.3.c.6.d — L1 polling: peek a pending cancel-goal request. Writes the named goal_id, the matching service sequence number, and the goal's current status (matches the rclc_goal_status_t discriminants — pass it back unchanged).

Returns 1 when a request was peeked, 0 when none pending, negative rcl_ret_t on error.

After a successful peek, call rclc_polling_action_server_send_cancel_reply_raw with the recorded sequence_number and the list of goals to accept-cancel.

◆ rclc_polling_action_server_try_recv_goal_request_raw()

int32_t rclc_polling_action_server_try_recv_goal_request_raw ( struct rclc_polling_action_server_t *  server,
uint8_t *  buf,
size_t  buf_len,
uint8_t(*)  goal_id_out[16],
int64_t *  sequence_number_out 
)

Phase 122.3.c.6.b — L1 polling: try to receive a goal request.

On success writes the goal payload bytes (already stripped of CDR framing) into buf, returns the number of bytes copied (>= 0), and fills goal_id_out (16 bytes) + sequence_number_out. Use the sequence number with rclc_polling_action_server_accept_goal_raw / _reject_goal_raw.

Returns 0 when no request is pending; negative rcl_ret_t on error.

◆ rclc_polling_client_fini()

rcl_ret_t rclc_polling_client_fini ( struct rclc_polling_client_t *  client)

Finalize a polled service client: drops the inline client, which closes the RMW entity.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if client is NULL
  • RCL_RET_NOT_INIT if it is not initialised
  • RCLC_RET_STALE_NODE if its node has already been finalised (issue 1386)

Safety

client must be a valid pointer.

◆ rclc_polling_client_init()

rcl_ret_t rclc_polling_client_init ( struct rclc_polling_client_t *  client,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name 
)

Phase 122.3.c.5 — initialize an L1 polling-mode service client.

Creates the underlying RMW client immediately and stores it inline in the client's _opaque field. The caller drives the request/reply cycle via rclc_polling_client_send_request_raw + rclc_polling_client_take_response_raw.

Parameters

  • client - Pointer to a zero-initialized client
  • node - Pointer to an initialized node
  • type_info - Pointer to service type information
  • service_name - Service name (null-terminated)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or name empty
  • RCL_RET_NOT_INIT if node / support not initialized
  • RCL_RET_ERROR if client creation failed

Safety

All pointers must be valid; service_name must be a valid null-terminated string.

◆ rclc_polling_client_request_publisher_get_actual_qos()

rcl_ret_t rclc_polling_client_request_publisher_get_actual_qos ( struct rclc_polling_client_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS a polled entity's backend GRANTED: the polled twin of [rclc_client_request_publisher_get_actual_qos], which carries the contract. Returns RCL_RET_NOT_INIT when the handle is not initialised.

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_polling_client_response_subscription_get_actual_qos()

rcl_ret_t rclc_polling_client_response_subscription_get_actual_qos ( struct rclc_polling_client_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS a polled entity's backend GRANTED: the polled twin of [rclc_client_response_subscription_get_actual_qos], which carries the contract. Returns RCL_RET_NOT_INIT when the handle is not initialised.

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_polling_client_send_request_raw()

rcl_ret_t rclc_polling_client_send_request_raw ( struct rclc_polling_client_t *  client,
const uint8_t *  data,
size_t  len 
)

Phase 122.3.c.5 — send a raw request on an L1 polling-mode client. Non-blocking. Poll for the reply via rclc_polling_client_take_response_raw.

Safety

client must be an initialized polling client. data readable for len bytes.

◆ rclc_polling_client_set_wake_callback()

rcl_ret_t rclc_polling_client_set_wake_callback ( struct rclc_polling_client_t *  client,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on an L1 polling-mode service client. Wakes when a reply lands. See rclc_polling_service_set_wake_callback for the lifetime contract.

◆ rclc_polling_client_take_response_raw()

int32_t rclc_polling_client_take_response_raw ( struct rclc_polling_client_t *  client,
uint8_t *  buf,
size_t  buf_len 
)

Phase 122.3.c.5 — non-blocking poll for a reply on an L1 polling-mode client. Writes reply bytes into the caller's buf.

Returns

  • >= 0 — number of bytes written to buf (0 = no reply yet)
  • RCL_RET_INVALID_ARGUMENT if pointers / state wrong
  • RCL_RET_ERROR on transport failure

Safety

client must be an initialized polling client. buf writable for buf_len bytes.

◆ rclc_polling_service_fini()

rcl_ret_t rclc_polling_service_fini ( struct rclc_polling_service_t *  service)

Finalize a polled service server: drops the inline server, which closes the RMW entity.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if service is NULL
  • RCL_RET_NOT_INIT if it is not initialised
  • RCLC_RET_STALE_NODE if its node has already been finalised — the teardown order was wrong, and nothing is dropped (issue 1386)

Safety

service must be a valid pointer.

◆ rclc_polling_service_init()

rcl_ret_t rclc_polling_service_init ( struct rclc_polling_service_t *  service,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name 
)

Phase 122.3.c.4 — initialize an L1 polling-mode service server.

Creates the underlying RMW server immediately and stores it inline in the service's _opaque field. The caller drains received requests via rclc_polling_service_take_request_raw and sends replies via rclc_polling_service_send_response_raw.

Parameters

  • service - Pointer to a zero-initialized service
  • node - Pointer to an initialized node
  • type_info - Pointer to service type information
  • service_name - Service name (null-terminated)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or name empty
  • RCL_RET_NOT_INIT if node / support not initialized
  • RCL_RET_ERROR if server creation failed

Safety

All pointers must be valid; service_name must be a valid null-terminated string.

◆ rclc_polling_service_request_subscription_get_actual_qos()

rcl_ret_t rclc_polling_service_request_subscription_get_actual_qos ( struct rclc_polling_service_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS a polled entity's backend GRANTED: the polled twin of [rclc_service_request_subscription_get_actual_qos], which carries the contract. Returns RCL_RET_NOT_INIT when the handle is not initialised.

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_polling_service_response_publisher_get_actual_qos()

rcl_ret_t rclc_polling_service_response_publisher_get_actual_qos ( struct rclc_polling_service_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS a polled entity's backend GRANTED: the polled twin of [rclc_service_response_publisher_get_actual_qos], which carries the contract. Returns RCL_RET_NOT_INIT when the handle is not initialised.

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_polling_service_send_response_raw()

rcl_ret_t rclc_polling_service_send_response_raw ( struct rclc_polling_service_t *  service,
int64_t  sequence_number,
const uint8_t *  data,
size_t  len 
)

Phase 122.3.c.4 — send a reply on an L1 polling-mode service.

sequence_number must equal the value returned by the most recent rclc_polling_service_take_request_raw for the request being replied to.

Safety

service must be an initialized polling service. data readable for len bytes.

◆ rclc_polling_service_set_wake_callback()

rcl_ret_t rclc_polling_service_set_wake_callback ( struct rclc_polling_service_t *  service,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on an L1 polling-mode service server. state must point to a rclc_wake_state_t allocated by the caller; it must outlive the service (typically declared inline next to the rclc_polling_service_t) and must not move after this call. Pass cb = NULL to disable. The backend wakes the callback when a new request arrives.

Safety

All pointers valid; state storage stable for the entity's lifetime.

◆ rclc_polling_service_take_request_raw()

int32_t rclc_polling_service_take_request_raw ( struct rclc_polling_service_t *  service,
uint8_t *  buf,
size_t  buf_len,
int64_t *  sequence_number 
)

Phase 122.3.c.4 — non-blocking poll for a pending request on an L1 polling-mode service. Writes the request bytes into the caller's buf and the matching sequence_number (required for reply).

Returns

  • >= 0 — number of bytes written to buf (0 = no request)
  • RCLC_RET_TRY_AGAIN if a request IS pending but every reply slot is held by a request not yet answered — send a response, then take again (issue 1088; distinct from the 0 that means nothing is pending)
  • RCL_RET_INVALID_ARGUMENT if pointers / state wrong
  • RCL_RET_ERROR on transport failure

Safety

service must be an initialized polling service. buf writable for buf_len bytes. sequence_number writable for i64.

◆ rclc_polling_subscription_borrow()

int32_t rclc_polling_subscription_borrow ( struct rclc_polling_subscription_t *  subscription,
const uint8_t **  out_buf,
size_t *  out_len,
void **  out_token 
)

Phase 124.A.6 — borrow a read-only view of the next available message in place (zero-copy receive path).

Availability: requires the lending AND alloc cargo features, and no shipped build enables lending — see rclc_publisher_loan for what that means for this header. Issue 0814.

Bypasses the subscription's staging buffer. On success, *out_buf points at *out_len bytes the caller can read directly. Caller MUST pass *out_token back to [rclc_polling_subscription_release] before requesting another borrow on the same subscription — only one outstanding view per subscription at a time.

Falls back to a take_serialized copy into the staging buffer when the active backend's vtable doesn't expose a native borrow slot.

Requires alloc as well as lending. Unlike the publish half — which issue 0812 made allocation-free by passing the BACKEND's own token through — the receive half still boxes a RecvView per borrow to manufacture a stable FFI token, so it cannot exist in a heap-free image. That was 0812's own "what this does NOT yet buy" item, and leaving the cfg at lending alone did not make it work: it made nros-c FAIL TO COMPILE under --features lending without alloc (four alloc::boxed::Box uses with no extern crate alloc in scope). A capability that cannot build is worse than one that is absent, so the cfg now states the real requirement (issue 0814).

Returns

  • > 0 — message length written into *out_len; view is ready.
  • 0 — no message ready right now.
  • negative — error (see rcl_ret_t).

Safety

  • subscription must be a valid polling subscription.
  • out_buf / out_len / out_token must be valid pointers.

◆ rclc_polling_subscription_fini()

rcl_ret_t rclc_polling_subscription_fini ( struct rclc_polling_subscription_t *  subscription)

Finalize a polled subscription: drops the inline subscriber, which closes the RMW entity.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if subscription is NULL
  • RCL_RET_NOT_INIT if it is not initialised
  • RCLC_RET_STALE_NODE if its node has already been finalised — the teardown order was wrong, and nothing is dropped (issue 1386).

Safety

  • subscription must be a valid pointer

◆ rclc_polling_subscription_get_actual_qos()

rcl_ret_t rclc_polling_subscription_get_actual_qos ( struct rclc_polling_subscription_t *  subscription,
struct rclc_qos_t *  out_qos 
)

The QoS profile a polled subscription is ACTUALLY running.

The polled twin of [rclc_subscription_get_actual_qos]: the subscriber is inline in the struct, so it answers directly.

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the polling subscription is not initialised

Safety

  • subscription must be a valid pointer.
  • out_qos must be a valid, writable rclc_qos_t.

◆ rclc_polling_subscription_init()

rcl_ret_t rclc_polling_subscription_init ( struct rclc_polling_subscription_t *  subscription,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name 
)

Phase 122.3.b — initialize an L1 polling-mode subscription.

Creates the underlying RMW subscriber immediately and stores it inline in the subscription's _opaque field. The caller drains received messages via rclc_polling_subscription_take_serialized.

Uses default QoS (RELIABLE, KEEP_LAST(10)). For custom QoS, use rclc_polling_subscription_init_with_qos.

Parameters

  • subscription - Pointer to a zero-initialized subscription
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or topic empty
  • RCL_RET_NOT_INIT if node / support not initialized
  • RCL_RET_ERROR if subscriber creation failed

Safety

  • All pointers must be valid
  • topic_name must be a valid null-terminated string

◆ rclc_polling_subscription_init_with_qos()

rcl_ret_t rclc_polling_subscription_init_with_qos ( struct rclc_polling_subscription_t *  subscription,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name,
const struct rclc_qos_t *  qos 
)

Phase 122.3.b — initialize an L1 polling-mode subscription with custom QoS.

See rclc_polling_subscription_init for the threading + lifecycle contract.

Safety

See rclc_polling_subscription_init.

◆ rclc_polling_subscription_release()

rcl_ret_t rclc_polling_subscription_release ( struct rclc_polling_subscription_t *  subscription,
void *  token 
)

Phase 124.A.6 — release a previously borrowed view.

Availability: requires lending AND alloc, and no shipped build enables lending — see rclc_publisher_loan. Issue 0814.

token MUST come from a prior rclc_polling_subscription_borrow on the SAME subscription; consuming it is mandatory before the subscription's next borrow / destroy.

Requires alloc as well as lending — it unboxes the RecvView its paired rclc_polling_subscription_borrow boxed. See that function.

Safety

  • subscription must be the subscription the token was borrowed from.
  • token must not be NULL and must not be reused after this call.

◆ rclc_polling_subscription_set_wake_callback()

rcl_ret_t rclc_polling_subscription_set_wake_callback ( struct rclc_polling_subscription_t *  subscription,
struct rclc_wake_state_t *  state,
void(*)(void *)  cb,
void *  ctx 
)

Phase 122.3.c.6.e — register a C wake callback on an L1 polling-mode subscription. state is a caller-owned rclc_wake_state_t (declared next to the subscription) that must outlive the subscription and not move. Pass cb = NULL to disable. The backend wakes the callback when a new message arrives.

Safety

All pointers valid; state storage stable for the subscription's lifetime.

◆ rclc_polling_subscription_take()

rcl_ret_t rclc_polling_subscription_take ( struct rclc_polling_subscription_t *  subscription,
void *  ros_message,
struct rmw_subscription_allocation_t *  allocation 
)

Take one sample from a polling subscription and DESERIALISE it into ros_message through the subscription's descriptor — the typed sibling of [rclc_polling_subscription_take_serialized] (phase-492 W8).

This is the rcl_take analog. rcl_take itself is not declared: it takes an rcl_subscription_t, which here is executor-owned (phase-487 W1, RFC-0096 D9) and has no subscriber of its own to take from, so the upstream name with this contract would compile and differ. A subscription the caller drains is an rclc_polling_subscription_t, and this is its take.

ros_message is the generated struct of the subscription's type, its strings and sequences wired to caller memory (<Msg>__init_in). The sample is read into the subscription's own receive buffer and decoded from there; nothing allocates.

Returns

  • RCL_RET_OK — one sample was taken and decoded into ros_message
  • RCLC_RET_TRY_AGAIN — nothing to take
  • RCL_RET_INVALID_ARGUMENT — a NULL argument, or a non-NULL allocation
  • RCLC_RET_BAD_SEQUENCE — not initialised
  • RCL_RET_UNSUPPORTED — the descriptor carries no deserialiser
  • RCL_RET_ERROR — the transport failed, or the sample did not decode (a field larger than its capacity): the sample is consumed and ros_message is not a valid message

Safety

  • subscription must be an initialised polling subscription.
  • ros_message must point at a message of the subscription's type.

◆ rclc_polling_subscription_take_sequence()

int32_t rclc_polling_subscription_take_sequence ( struct rclc_polling_subscription_t *  subscription,
uint8_t *  buf,
size_t  per_msg_cap,
size_t  max_msgs,
size_t *  out_lens 
)

Phase 124.D.1 — burst-take. Drain up to max_msgs queued samples into the contiguous buf block in a single call, with the i-th sample at buf + i * per_msg_cap and length out_lens[i].

buf is a caller-owned contiguous region of at least max_msgs * per_msg_cap bytes. out_lens is a writable array of at least max_msgs size_t slots.

Returns the number of messages delivered (>= 0) on success, or a negative rcl_ret_t error code. Partial drains are reported as the count, never as an error.

Safety

  • subscription must be an initialized polling subscription.
  • buf must point to writable memory of at least max_msgs * per_msg_cap bytes.
  • out_lens must point to a writable array of at least max_msgs size_t slots.

◆ rclc_polling_subscription_take_serialized()

int32_t rclc_polling_subscription_take_serialized ( struct rclc_polling_subscription_t *  subscription,
uint8_t *  buf,
size_t  buf_len 
)

Phase 122.3.b — non-blocking poll on an L1 polling-mode subscription. Returns the number of bytes received on success (may be 0 if no data available), or a negative rcl_ret_t on error.

Parameters

  • subscription - Pointer to an initialized polling subscription
  • buf - Caller-supplied buffer to receive the message bytes
  • buf_len - Capacity of buf

Returns

  • >= 0 — number of bytes copied into buf
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or state is wrong
  • RCL_RET_ERROR on transport failure

Safety

  • subscription must be an initialized polling subscription
  • buf must point to writable memory of at least buf_len bytes

◆ rclc_polling_subscription_take_validated()

int32_t rclc_polling_subscription_take_validated ( struct rclc_polling_subscription_t *  subscription,
uint8_t *  buf,
size_t  buf_len,
struct rclc_integrity_status_t *  out_status 
)

Phase 252 / issue 0073 — non-blocking poll that ALSO returns the E2E integrity status (CRC + sequence gap/dup) of the received sample. The safety-e2e analog of [rclc_polling_subscription_take_serialized]: it requests validation on the backend (the zenoh shim recomputes + compares the CRC attachment and tracks the sequence) and writes the verdict to *out_status.

Requires the build to enable safety-e2e on both ends (the zenoh backend's own feature, lowered from a declared [safety] axis); otherwise crc_valid reports -1 (no CRC on the wire).

Returns

  • >= 0 — number of bytes copied into buf (0 = no data available)
  • RCL_RET_INVALID_ARGUMENT if subscription/buf is NULL
  • RCLC_RET_BAD_SEQUENCE if the polling subscription is not initialized
  • RCL_RET_ERROR on transport failure

Safety

  • subscription must be an initialized polling subscription
  • buf must point to writable memory of at least buf_len bytes
  • out_status, if non-NULL, must point to a writable rclc_integrity_status_t

◆ rclc_publish_raw()

rcl_ret_t rclc_publish_raw ( const struct rcl_publisher_t *  publisher,
const uint8_t *  data,
size_t  len 
)

Publish raw CDR-serialized data.

Parameters

  • publisher - Pointer to an initialized publisher
  • data - Pointer to CDR-serialized message data
  • len - Length of data in bytes

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL or len is 0
  • RCL_RET_NOT_INIT if publisher is not initialized
  • RCLC_RET_PUBLISH_FAILED on publish failure

Safety

  • publisher must be a valid pointer to an initialized publisher
  • data must be a valid pointer to len bytes

◆ rclc_publisher_commit()

rcl_ret_t rclc_publisher_commit ( const struct rcl_publisher_t *  publisher,
void *  token,
size_t  actual_len 
)

Phase 124.A.6 — commit a previously-loaned slot. Sends the slot's actual_len bytes via the active backend.

Availability: lending-only, and no shipped build enables it — see rclc_publisher_loan. Issue 0814.

token MUST come from a prior rclc_publisher_loan on the SAME publisher; consuming it (commit OR discard) is mandatory.

Safety

  • publisher must be the same publisher the token was loaned from.
  • token must not be NULL and must not be reused after this call.

◆ rclc_publisher_discard()

rcl_ret_t rclc_publisher_discard ( const struct rcl_publisher_t *  publisher,
void *  token 
)

Phase 124.A.6 — abandon a previously-loaned slot without sending.

Availability: lending-only, and no shipped build enables it — see rclc_publisher_loan. Issue 0814.

token MUST come from a prior rclc_publisher_loan on the SAME publisher; consuming it (commit OR discard) is mandatory.

Safety

  • publisher must be the same publisher the token was loaned from.
  • token must not be NULL and must not be reused after this call.

◆ rclc_publisher_get_actual_qos()

rcl_ret_t rclc_publisher_get_actual_qos ( const struct rcl_publisher_t *  publisher,
struct rclc_qos_t *  out_qos 
)

The QoS profile this publisher is ACTUALLY running — issue 1437.

rcl_publisher_get_actual_qos. What the BACKEND GRANTED, which differs from what rclc_publisher_init_with_qos was handed whenever the backend serves something else (zenoh clamps history depth to its receive ring; DDS negotiates; a launch-lowered rclc_node_set_qos_overrides row has already been folded in before either). That difference is what answers "why is nothing arriving": a RELIABLE reader does not match a BEST_EFFORT writer, and a clamped depth drops samples the caller believed were kept.

Per policy, and a policy the backend cannot report is an ABSENCE, not your request echoed back: it reads NROS_QOS_*_UNKNOWN. A backend with no read-back at all (XRCE) answers UNKNOWN in every field. Compare against your request field by field; do NOT assume agreement where you find it without checking for the sentinel first.

Free: the profile was read once at create and retained, so this never re-enters the transport and is safe from a callback.

Parameters

  • publisher - an initialized publisher
  • out_qos - written on success; untouched on every error

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the publisher is not initialized

Shape, and why it is not upstream's

rcl returns const rmw_qos_profile_t * — an interior pointer into the handle. That costs a retained rclc_qos_t in every rcl_publisher_t, i.e. RAM in every image including those that never ask, and it hands out a pointer whose lifetime the caller has to reason about with no ownership types to help. An out-parameter plus a status is this API's own shape (RFC-0018), and it is the shape that lets the NOT_INIT case be reported rather than encoded as NULL.

Safety

  • publisher must be a valid pointer to an initialized publisher.
  • out_qos must be a valid, writable rclc_qos_t.

◆ rclc_publisher_get_gid()

rcl_ret_t rclc_publisher_get_gid ( const struct rcl_publisher_t *  publisher,
uint8_t *  out_gid,
size_t  gid_capacity 
)

This publisher's own global identifier — upstream rmw_get_gid_for_publisher.

The phase-467 RMW gap-closure design study's Q1. Writes NROS_PUBLISHER_GID_SIZE (24) bytes into out_gid and touches nothing on failure.

Three bounds, each of which a caller will otherwise assume away:

  • How many of the 24 bytes MEAN anything is a backend property. A backend whose identity is narrower zero-extends into the tail, so two gids naming one entity compare equal. Gids from two different backends in one image are never comparable.
  • Comparable with the gid on a received sample on zenoh and Cyclone, which derive both from one source (issue 1495).
  • An all-zero gid is never returned as an answer. A backend with no identity for this publisher reports RCL_RET_UNSUPPORTED, because all-zero is what an unwritten buffer holds and the two must not read alike.

Parameters

  • publisher — pointer to an initialized publisher
  • out_gid — buffer of at least gid_capacity bytes, filled on RCL_RET_OK
  • gid_capacity — how many bytes out_gid can hold. CHECKED, not assumed. The C surface has no nros_gid_t, so the out-param is a bare uint8_t * that carries no width of its own, and the callee's only alternative to a capacity argument is to write 24 bytes on the caller's word. The width is also not a constant that has held still: the Rust PUBLISHER_GID_SIZE this mirrors was 16 until the same study's Q1(a).

Returns

  • RCL_RET_OK — out_gid[0 .. NROS_PUBLISHER_GID_SIZE] written
  • RCL_RET_INVALID_ARGUMENT — a NULL argument, or gid_capacity < NROS_PUBLISHER_GID_SIZE
  • RCL_RET_NOT_INIT if not initialized
  • RCL_RET_UNSUPPORTED — this backend has no identity for this publisher (XRCE-DDS, uORB)
  • RCL_RET_ERROR — the backend was asked and failed

Safety

  • publisher must be a valid pointer to an initialized publisher.
  • out_gid must be writable for gid_capacity bytes.

◆ rclc_publisher_get_subscription_count()

rcl_ret_t rclc_publisher_get_subscription_count ( const struct rcl_publisher_t *  publisher,
struct rclc_executor_t *  executor,
size_t *  out_count 
)

How many subscriptions are on this publisher's topic, right now.

rcl's rcl_publisher_get_subscription_count with an executor parameter, hence the distinct rclc_ name (phase-492 W1.b) — phase-444, ledger row c:publisher_get_subscription_count.

A WEAKER QUESTION THAN UPSTREAM'S, stated here rather than discovered

Upstream counts the subscriptions MATCHED to THIS publisher — peers whose QoS is compatible with it. This counts every subscription DISCOVERED on the topic, matched or not, because that is what the graph can answer and a backend with no QoS negotiation cannot tell the two apart at all.

Non-inverting, and in the safe direction: a topic nobody subscribes to still reads 0, so the use this exists for — skip the work when nobody is listening — is answered exactly. An INCOMPATIBLE peer makes it read 1 where upstream reads 0, i.e. you do work nobody receives. Never the reverse.

The EXECUTOR parameter, which upstream does not take

We open ONE transport session per image and the executor owns it, so the graph is the executor's to read — the same receiver difference as every rclc_executor_get_* graph verb (phase-381 W4). The name was upstream's, counting on the extra argument to make a porter notice; RFC-0089's 2026-10-12 rule 2 forbids an upstream name over a different arity, so it is rclc_ (phase-492 W1.b) and a ported call fails on the name.

Parameters

  • publisher - Pointer to a publisher
  • executor - The executor whose session sees the graph
  • out_count - Receives the count

Returns

  • RCL_RET_OK — *out_count written.
  • RCL_RET_INVALID_ARGUMENT — a NULL pointer.
  • RCL_RET_NOT_INIT — publisher or executor not usable.
  • RCL_RET_UNSUPPORTED — the backend cannot read the graph (XRCE). A DIFFERENT answer from 0, and *out_count is not written.

Safety

  • publisher and executor must be valid pointers or NULL
  • out_count must point to a writable size_t or be NULL

◆ rclc_publisher_init_default()

rcl_ret_t rclc_publisher_init_default ( struct rcl_publisher_t *  publisher,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name 
)

Initialize a publisher with default QoS (RELIABLE, KEEP_LAST(10)).

This is the recommended initialization function for most use cases. Uses QOS_PROFILE_DEFAULT which provides reliable delivery.

Parameters

  • publisher - Pointer to a zero-initialized publisher
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated string)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All pointers must be valid
  • topic_name must be a valid null-terminated string

◆ rclc_publisher_init_with_options()

rcl_ret_t rclc_publisher_init_with_options ( struct rcl_publisher_t *  publisher,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name,
const struct rclc_qos_t *  qos,
const struct rcl_publisher_options_t *  options 
)

Phase 189.M3 — initialize a publisher with custom QoS + named options.

rclc-style entry point: QoS is passed separately (qos, NULL = default) and the non-QoS axes ride in options (NULL = defaults). Equivalent to [rclc_publisher_init_with_qos] today — [rcl_publisher_options_t] is currently a reserved, thin struct (publishers have no scheduling-context binding) — but kept as a distinct, additive entry point for rclc symmetry and forward ABI headroom.

Parameters

  • publisher - Pointer to a zero-initialized publisher
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated string)
  • qos - Pointer to QoS settings (NULL for default)
  • options - Pointer to publisher options (NULL for defaults)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All required pointers must be valid
  • topic_name must be a valid null-terminated string
  • qos / options may be NULL or point to valid structs

◆ rclc_publisher_init_with_qos()

rcl_ret_t rclc_publisher_init_with_qos ( struct rcl_publisher_t *  publisher,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name,
const struct rclc_qos_t *  qos 
)

Initialize a publisher with custom QoS.

Parameters

  • publisher - Pointer to a zero-initialized publisher
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated string)
  • qos - Pointer to QoS settings (NULL for default)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All required pointers must be valid
  • topic_name must be a valid null-terminated string

◆ rclc_publisher_loan()

rcl_ret_t rclc_publisher_loan ( const struct rcl_publisher_t *  publisher,
size_t  requested_len,
uint8_t **  out_buf,
size_t *  out_cap,
void **  out_token 
)

Phase 124.A.6 — loan a writable slot from the publisher's outbound buffer (zero-copy publish path).

AVAILABILITY — read this before calling

This symbol exists only in a nano-ros built with the lending cargo feature, and no shipped configuration enables it: the string lending appears zero times under cmake/ and zephyr/, nros-rmw-zenoh-staticlib — the crate every C/C++ and RTOS image links — declares no forwarder for it, and the only crate in the tree that turns it on is the nros-tests test harness.

Its presence in this header is therefore not evidence that it can be linked. cbindgen emits every declaration unconditionally here, by deliberate repo-wide policy (packages/api/nros-c/cbindgen.toml [defines], empty on purpose), so a #[cfg]-gated Rust symbol still appears. Calling this against a default build compiles and then fails at LINK with an undefined symbol.

The supported zero-copy surface is rclc_publisher_publish_streamed and its receive twin process_raw_in_place: no feature, no token, no arena, no size ceiling, and the XRCE and zenoh backends fill them natively while all three NULL the loan trio. See issue 0814.

On success, *out_buf points at *out_cap writable bytes the caller fills in place. Pass *out_token back to [rclc_publisher_commit] (to send) or [rclc_publisher_discard] (to abandon). The slot's bytes are valid until commit / discard runs OR the publisher is finalised — whichever comes first. The caller is responsible for matching every loan with exactly one commit OR discard.

Falls back to a heap-allocated staging buffer when the active backend's vtable doesn't expose a native loan slot — the wire payload still takes a single memcpy at commit time. requested_len is the minimum capacity; *out_cap may exceed it. That fallback needs a heap: in a build without alloc there is nothing to hand out, and the answer is RCLC_RET_NOT_ALLOWED (see below).

Returns

  • RCL_RET_OK — slot reserved.
  • RCLC_RET_TRY_AGAIN (-14) — no slot available right now. TRANSIENT: retry later, or use a non-loan publish path.
  • RCLC_RET_NOT_ALLOWED (-12) — this publisher cannot loan at all. PERMANENT (issue 0814): the backend's vtable exposes no loan slot and this build has no heap for the staging fallback, and neither fact can change while the publisher lives. Do NOT retry — take a non-loan path. rclc_publisher_publish_streamed is the better one: it needs no token, no arena and no heap, and the XRCE and zenoh backends fill it natively.
  • RCL_RET_INVALID_ARGUMENT on NULL pointers or zero requested_len.
  • RCL_RET_NOT_INIT if publisher isn't initialised.

Safety

  • All pointers must be valid.

◆ rclc_publisher_publish_streamed()

rcl_ret_t rclc_publisher_publish_streamed ( const struct rcl_publisher_t *  publisher,
void(*)(size_t *out_total_len, void *user_ctx)  size_cb,
void(*)(uint8_t *out_buf, size_t cap, size_t *out_written, void *user_ctx)  chunk_cb,
void *  user_ctx 
)

Phase 124.E.1 — streamed publish.

Two callbacks: size_cb reports the total payload length once, chunk_cb fills the slot in chunks. Backends that support streaming land each chunk directly in their outbound buffer; backends that don't fall through to a stack-allocated staging buffer (capped at ~4 KiB) + a single publish_raw.

Parameters

  • publisher — initialized publisher
  • size_cb — invoked once; writes the total byte count to *out_total_len
  • chunk_cb — invoked repeatedly; writes up to cap bytes starting at out_buf, reports the count via *out_written. *out_written == 0 signals EOF
  • user_ctx — opaque pointer passed through to both callbacks

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if not initialised
  • RCLC_RET_PUBLISH_FAILED on backend failure — INCLUDING a payload larger than the fallback's ~4 KiB staging buffer, and a chunk_cb that reports 0 written before *out_total_len bytes have been produced. This line used to name a NROS_RET_-prefixed BUFFER_TOO_SMALL (issue 1126): rcl_ret_t has never defined one — the constant is NROS_RMW_RET_BUFFER_TOO_SMALL, on the RMW ABI (nros_rmw_ret_t), and a C caller writing the documented comparison got an undeclared identifier with nothing pointing back here. The backend errors collapse to one code on the way out, so the two causes are NOT distinguishable by the caller; for this entry point that is tolerable, since the caller sized the payload it streamed.

Safety

  • publisher must be a valid pointer to an initialised publisher.
  • The callbacks MUST NOT return references that outlive the call; user_ctx is valid only for the duration of the call.

◆ rclc_publisher_set_liveliness_lost_callback()

rcl_ret_t rclc_publisher_set_liveliness_lost_callback ( struct rcl_publisher_t *  _pub_,
rclc_event_publisher_count_cb_t  _cb,
void *  _user_context 
)

Register a callback for NROS_EVENT_LIVELINESS_LOST.

Safety

pub_ must point to a valid, initialised rcl_publisher_t. cb must be a valid function pointer or None.

◆ rclc_publisher_set_offered_deadline_missed_callback()

rcl_ret_t rclc_publisher_set_offered_deadline_missed_callback ( struct rcl_publisher_t *  _pub_,
uint32_t  _deadline_ms,
rclc_event_publisher_count_cb_t  _cb,
void *  _user_context 
)

Register a callback for NROS_EVENT_OFFERED_DEADLINE_MISSED.

deadline_ms is the publisher's offered minimum-rate window.

Safety

See [rclc_publisher_set_liveliness_lost_callback].

◆ rclc_qos_policy_kind_to_cstr()

const char * rclc_qos_policy_kind_to_cstr ( uint32_t  policy)

The name of ONE QoS policy — phase-417 G7, the C half of rclcpp::qos_policy_kind_to_cstr.

Parameters
policyOne NROS_RMW_QOS_POLICY_* bit from <nros/rmw_entity.h> — the same twelve bits a backend advertises through the vtable's supported_qos_policies slot, and the same twelve QoSPolicyMask carries in Rust. check-qos-mask-derivation holds those two vocabularies equal name for name and bit for bit, so this function has exactly one table behind it however you reach it.
Returns
A borrowed, NUL-terminated, 'static string — "RELIABILITY", "DEADLINE", … — or NULL when policy is not exactly one policy bit. Never freed, never allocated: the bytes are in flash, which is what makes this usable from a freestanding image.

NULL rather than "UNKNOWN" for zero and for a union: both are real answers, and a caller that prints a name it was handed must be able to tell "no policy was identified" from a policy that was. rclcpp's own version returns "Invalid" for its invalid enumerator; we have no invalid enumerator to return a word for, because our vocabulary is a bitmask and the empty mask is a legitimate value.

This is why the name exists at all (ledger cpp:qos_policy_kind_to_cstr): an INCOMPATIBLE_QOS return names no policy by itself, and naming the policy IS the diagnostic. No table of its own — the pointer is QoSPolicyMask::NAMED's own bytes, which is the whole point of the row. nros-c restating the twelve identifiers here would be the parallel table this campaign has paid for twice (the RMW parity map's 28 stale slots, the layout gate's three authored type names).

◆ rclc_service_init_default()

rcl_ret_t rclc_service_init_default ( struct rcl_service_t *  service,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name 
)

rclc's rclc_service_init_default, in rclc's argument order and at rclc's ARITY (phase-417 stage 6). The old nros_service_init carried callback and context in positions 5 and 6; RFC-0089 records that the binding site was never mandated (RFC-0041 governs the DISPATCH MODEL, and executor-owns-no-entity-storage is defined nowhere), so the callback moves to registration where rclc puts it — rclc_executor_add_service_raw.

The typesupport parameter keeps OUR type for the reason RFC-0089 settled on 2026-09-04: a rosidl typesupport's members are its contract, including a func dispatcher we do not have.

The six-argument nros_service_init is GONE (phase-417 stage 6 step B retired it), and since phase-487 no init entry point takes a callback.

Safety

All non-NULL pointers must be valid + the node initialized.

◆ rclc_service_init_with_options()

rcl_ret_t rclc_service_init_with_options ( struct rcl_service_t *  service,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name,
const struct rclc_qos_t *  qos,
const struct rcl_service_options_t *  options 
)

Phase 189.M3.3.a — initialize a service server with custom QoS + named options. Behaves like [rclc_service_init_with_qos] except a non-zero options->sched_context is stashed on the service so that rclc_executor_add_service_raw binds the resulting executor handle to that scheduling context once the handle is known (server creation is deferred to registration, so the handle does not exist at init time).

Safety

All non-NULL pointers must be valid + the node initialized; qos / options may be NULL.

◆ rclc_service_init_with_qos()

rcl_ret_t rclc_service_init_with_qos ( struct rcl_service_t *  service,
const struct rcl_node_t *  node,
const struct rclc_service_type_t *  type_info,
const char *  service_name,
const struct rclc_qos_t *  qos 
)

Initialize a service server with an explicit QoS profile.

Parameters

  • service - Pointer to a zero-initialized service
  • node - Pointer to an initialized node
  • type_info - Pointer to service type information
  • service_name - Service name (null-terminated string)
  • qos - QoS for both endpoints, or NULL for the services default

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

phase-487 W2 removed the callback and context this took between the name and the QoS: the struct stored them only for the (since removed) two-argument nros_executor_add_service to read back, while the arena entry kept its own copies. The callback is supplied at registration, by rclc_executor_add_service_raw or a generated <Srv>_executor_add_service, as rclc supplies it at rclc_executor_add_service.

◆ rclc_service_request_subscription_get_actual_qos()

rcl_ret_t rclc_service_request_subscription_get_actual_qos ( const struct rcl_service_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS the backend GRANTED this service's REQUEST endpoint — the subscription that receives calls.

rcl_service_request_subscription_get_actual_qos. A policy the backend could not report reads back as NROS_QOS_*_UNKNOWN, never as your request — see [rclc_publisher_get_actual_qos](crate::publisher::rclc_publisher_get_actual_qos).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the handle is in no usable state, or is callback-mode and not yet added to an executor — there is no entity to ask, which is a different answer from UNKNOWN ("there is an entity and it cannot say")

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_service_response_publisher_get_actual_qos()

rcl_ret_t rclc_service_response_publisher_get_actual_qos ( const struct rcl_service_t *  handle,
struct rclc_qos_t *  out_qos 
)

The QoS the backend GRANTED this service's RESPONSE endpoint — the publisher that sends replies.

rcl_service_response_publisher_get_actual_qos. A policy the backend could not report reads back as NROS_QOS_*_UNKNOWN, never as your request — see [rclc_publisher_get_actual_qos](crate::publisher::rclc_publisher_get_actual_qos).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the handle is in no usable state, or is callback-mode and not yet added to an executor — there is no entity to ask, which is a different answer from UNKNOWN ("there is an entity and it cannot say")

Safety

Both pointers must be valid; out_qos must be writable.

◆ rclc_service_typed_report_error()

void rclc_service_typed_report_error ( int32_t  error,
const char *  type_name 
)

Report a typed service/client glue failure as an ERROR log record.

Called by the generated static inline trampolines. error is one of the NROS_SERVICE_TYPED_ERR_* codes above; type_name is the service type's own <Srv>_get_type_name(), so the record names the type without the generated header having to duplicate any string.

Deliberately returns nothing and cannot fail: it is the loudness path, and a loudness path that itself has an error channel just moves the silence.

Safety

type_name is NULL or a NUL-terminated string readable for its length.

◆ rclc_set_custom_transport()

rcl_ret_t rclc_set_custom_transport ( const struct nros_transport_ops_t *  ops)

Phase 115.C — register a custom transport vtable.

Must be called BEFORE rclc_support_init. Subsequent calls before init overwrite the slot. After init, behaviour is implementation-defined — the active RMW backend may have already consumed the previously-registered vtable.

Pass NULL to clear a previously-registered vtable.

Returns

  • RCL_RET_OK on success.
  • RCL_RET_INVALID_ARGUMENT if ops is non-NULL but any of the four function pointers is NULL.

Safety

The four function pointers in ops must follow the threading contract documented in <nros/transport.h>.

◆ rclc_set_default_trace_sink()

int32_t rclc_set_default_trace_sink ( void(*)(uint32_t, uint32_t)  sink)

Install sink as the callback trace sink only if none is installed yet.

Returns 1 when sink was installed, 0 when a sink was already installed (it is kept) or the crate was built without trace-callbacks.

For an entry path's DEFAULT sink: the Zephyr tier runner installs its platform shim this way, so a sink the application installed earlier (from a SYS_INIT, before main()) is not replaced.

Safety

As [rclc_set_trace_sink]: sink must be a valid function pointer with that C ABI, re-entrant, and must not unwind.

◆ rclc_set_trace_sink()

void rclc_set_trace_sink ( void(*)(uint32_t, uint32_t)  sink)

Install the callback trace sink, or clear it with NULL.

sink is called as sink(marker_id, arg) — the signature of a two-uint32 platform trace event, chosen so a platform shim is installable verbatim:

marker_id event arg
16 register handle << 8 \| kind
17 name next 4 name bytes, byte i in bits 8*i
18 start handle
19 end handle

and, with the later blocks, 20 (handle-tagged name chunk), 21-24 (a stored contract violation, phase-474 I1) and 25-27 (a take and its source stamp, phase-474 I3, see [rclc_trace_set_take]); the full table is in nros_node::executor::callback_trace.

Call it once at startup, BEFORE anything is registered on the executor: a sink installed later misses the registration events, and the decoder then has handles with no names.

No-op unless the crate was built with trace-callbacks.

Safety

sink must be a valid function pointer with the C ABI above, or NULL. It is called from the executor's dispatch path — including from an OS-priority worker task, i.e. a different thread — so it must be re-entrant and must not unwind. It must remain valid until it is replaced or cleared.

◆ rclc_subscription_get_actual_qos()

rcl_ret_t rclc_subscription_get_actual_qos ( const struct rcl_subscription_t *  subscription,
struct rclc_qos_t *  out_qos 
)

The QoS profile this subscription is ACTUALLY running — issue 1437.

rcl_subscription_get_actual_qos. See [rclc_publisher_get_actual_qos](crate::publisher::rclc_publisher_get_actual_qos) for what "actual" means, why an unreportable policy reads back as NROS_QOS_*_UNKNOWN rather than as your request, and why this API returns a status with an out-parameter where rcl returns an interior pointer.

The executor arena owns this subscription's subscriber and the handle carries only (executor, handle_id), so the answer is read through the arena. A polled subscription answers through [rclc_polling_subscription_get_actual_qos].

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if either pointer is NULL
  • RCL_RET_NOT_INIT if the subscription is not initialised, or has not been added to an executor yet — there is no entity to ask, which is a different answer from UNKNOWN ("there is an entity and it cannot say")

Safety

  • subscription must be a valid pointer to an initialized subscription.
  • out_qos must be a valid, writable rclc_qos_t.

◆ rclc_subscription_get_publisher_count()

rcl_ret_t rclc_subscription_get_publisher_count ( const struct rcl_subscription_t *  subscription,
struct rclc_executor_t *  executor,
size_t *  out_count 
)

How many publishers are on this subscription's topic, right now.

rcl's rcl_subscription_get_publisher_count with an executor parameter, hence the distinct rclc_ name (phase-492 W1.b) — phase-444, ledger row c:subscription_get_publisher_count. The subscription half of [rclc_publisher_get_subscription_count](crate::publisher::rclc_publisher_get_subscription_count), which states the weakening (topic-wide, not matched-to-this-entity), why the executor is a parameter, and why RCL_RET_UNSUPPORTED is not 0.

Parameters

  • subscription - Pointer to a subscription
  • executor - The executor whose session sees the graph
  • out_count - Receives the count

Safety

  • subscription and executor must be valid pointers or NULL
  • out_count must point to a writable size_t or be NULL

◆ rclc_subscription_init_default()

rcl_ret_t rclc_subscription_init_default ( struct rcl_subscription_t *  subscription,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name 
)

Initialize a subscription with default QoS (RELIABLE, KEEP_LAST(10)).

rclc's rclc_subscription_init_default, in rclc's argument order and at rclc's ARITY (phase-417 stage 6). The old nros_subscription_init carried two extra arguments — callback and context — and RFC-0089 records why they are gone from here:

  • the binding site was never mandated. RFC-0041 is about the DISPATCH MODEL, not about which call first supplies a callback, and executor-owns-no-entity-storage — cited by name in ten ledger rows as the reason — is defined nowhere in docs/design/;
  • the only real constraint found (c:timer_exchange_callback) forbids SWAPPING a callback on a live entity, which registration-time binding does not do.

So the callback is supplied where rclc supplies it, at registration: rclc_executor_add_subscription_with_context for the typed path (rclc's own, phase-492 W8) and rclc_executor_add_subscription_raw for the byte path, which has no rclc counterpart and therefore takes an ours-only name.

The typesupport parameter stays const rclc_message_type_t * rather than taking rosidl_message_type_support_t's name: a rosidl typesupport's MEMBERS are its contract, including the func dispatcher we do not have, so adopting the name would claim a structure we lack (RFC-0089, settled 2026-09-04). It costs a ported call site nothing — the argument comes from our codegen either way.

The six-argument nros_subscription_init is GONE (phase-417 stage 6 step B retired it), and since phase-487 no init entry point takes a callback: the subscription struct no longer has anywhere to keep one, because the executor arena owns it.

Parameters

  • subscription - Pointer to a zero-initialized subscription
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated string)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All required pointers must be valid
  • topic_name must be a valid null-terminated string

◆ rclc_subscription_init_with_options()

rcl_ret_t rclc_subscription_init_with_options ( struct rcl_subscription_t *  subscription,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name,
const struct rclc_qos_t *  qos,
const struct rcl_subscription_options_t *  options 
)

Phase 189.M3 — initialize a subscription with custom QoS + named options.

rclc-style entry point: QoS is passed separately (qos, NULL = default) and the non-QoS axes ride in options (NULL = defaults). Behaves exactly like [rclc_subscription_init_with_qos] except that a non-zero options->sched_context is stashed on the subscription so that nros_executor_add_subscription_* binds the resulting executor handle to that scheduling context once the handle is known (entity creation is deferred to registration, so the handle does not exist at init time). options->message_info is RESERVED and ignored (Phase 189.M3.4).

Parameters

  • subscription - Pointer to a zero-initialized subscription
  • node - Pointer to an initialized node
  • type_info - Pointer to message type information
  • topic_name - Topic name (null-terminated string)
  • qos - Pointer to QoS settings (NULL for default)
  • options - Pointer to subscription options (NULL for defaults)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL
  • RCL_RET_NOT_INIT if node is not initialized
  • RCL_RET_ERROR on initialization failure

Safety

  • All required pointers must be valid
  • topic_name must be a valid null-terminated string
  • qos / options may be NULL or point to valid structs

◆ rclc_subscription_init_with_qos()

rcl_ret_t rclc_subscription_init_with_qos ( struct rcl_subscription_t *  subscription,
const struct rcl_node_t *  node,
const struct rclc_message_type_t *  type_info,
const char *  topic_name,
const struct rclc_qos_t *  qos 
)

Initialize a subscription with custom QoS.

rclc's rclc_subscription_init shape: (subscription, node, type, topic, qos). phase-487 W1 removed the callback and context this took between the topic and the QoS. The struct stored them only for the (since removed) three-argument nros_executor_add_subscription to read back, and the arena kept its own copies; the callback is now supplied at registration, by rclc_executor_add_subscription_raw / _typed / _with_info.

Safety

  • All required pointers must be valid
  • topic_name must be a valid null-terminated string
  • qos may be NULL (default) or point to a valid rclc_qos_t

◆ rclc_subscription_set_liveliness_changed_callback()

rcl_ret_t rclc_subscription_set_liveliness_changed_callback ( struct rcl_subscription_t *  _sub,
rclc_event_liveliness_changed_cb_t  _cb,
void *  _user_context 
)

Register a callback for NROS_EVENT_LIVELINESS_CHANGED.

Returns NROS_RMW_RET_UNSUPPORTED until the active backend wires up liveliness-event detection (Phase 109+). Applications can call it today; the event fires once the backend gains support.

Safety

sub must point to a valid, initialised rcl_subscription_t. cb must be a valid function pointer or None. user_context is opaque to nros and must outlive the subscription.

◆ rclc_subscription_set_message_lost_callback()

rcl_ret_t rclc_subscription_set_message_lost_callback ( struct rcl_subscription_t *  _sub,
rclc_event_subscriber_count_cb_t  _cb,
void *  _user_context 
)

Register a callback for NROS_EVENT_MESSAGE_LOST.

Safety

See [rclc_subscription_set_liveliness_changed_callback].

◆ rclc_subscription_set_requested_deadline_missed_callback()

rcl_ret_t rclc_subscription_set_requested_deadline_missed_callback ( struct rcl_subscription_t *  _sub,
uint32_t  _deadline_ms,
rclc_event_subscriber_count_cb_t  _cb,
void *  _user_context 
)

Register a callback for NROS_EVENT_REQUESTED_DEADLINE_MISSED.

deadline_ms is the maximum acceptable inter-arrival time for expected samples. When a sample doesn't arrive within this window, the callback fires.

Safety

See [rclc_subscription_set_liveliness_changed_callback].

◆ rclc_support_fini()

rcl_ret_t rclc_support_fini ( struct rclc_support_t *  support)

Finalize the support context.

This function closes the middleware session and releases all resources.

Parameters

  • support - Pointer to an initialized support context

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if support is NULL
  • RCL_RET_NOT_INIT if not initialized

Safety

◆ rclc_support_get_zero_initialized()

struct rclc_support_t rclc_support_get_zero_initialized ( void  )

Get a zero-initialized support context.

Safety

Returns a stack-allocated struct that must be initialized before use.

◆ rclc_support_init()

rcl_ret_t rclc_support_init ( struct rclc_support_t *  support,
int  argc,
const char *const *  argv,
const struct rcl_allocator_t *  allocator 
)

Initialize the support context — rclc's signature (phase-492 W1.b).

rclc_support_init(&support, argc, argv, &allocator), as an rclc program writes it. The locator and domain come from the build and, on a hosted target, the environment (NROS_LOCATOR, ROS_DOMAIN_ID), exactly as [rclc_support_init_with_locator] resolves them when given NULL and 0.

The envelope: argv may carry program arguments, which are ignored as rcl ignores non-ROS ones, but --ros-args is REFUSED with RCL_RET_UNSUPPORTED — the C binding has no ROS-argument parser, and dropping remaps silently would run a different graph. allocator must be NULL or rcl_get_default_allocator()'s (nothing here allocates).

Safety

  • support must point to a zero-initialized rclc_support_t.
  • argv must hold argc NUL-terminated strings, or be NULL with argc 0.
  • allocator must be NULL or readable.

◆ rclc_support_init_named()

rcl_ret_t rclc_support_init_named ( struct rclc_support_t *  support,
const char *  locator,
uint8_t  domain_id,
const char *  session_name 
)

Initialize the support context with a session name.

Like rclc_support_init, but allows specifying a session name for XRCE-DDS. Different XRCE clients on the same agent MUST use different session names; otherwise the agent treats them as the same client and won't relay data between them.

Parameters

  • support - Pointer to a zero-initialized support context
  • locator - Middleware locator string, or NULL for default
  • domain_id - ROS domain ID (0-232)
  • session_name - Session name for XRCE key derivation, or NULL for default

Safety

  • support must be a valid pointer to a zero-initialized rclc_support_t
  • locator and session_name must be valid null-terminated strings or NULL

◆ rclc_support_init_rmw()

rcl_ret_t rclc_support_init_rmw ( struct rclc_support_t *  support,
const char *  locator,
uint8_t  domain_id,
const char *  session_name,
const char *  rmw 
)

Issue 1050 defect (3) — [rclc_support_init_named] with an explicit RMW selector.

rmw is the BAKED rung of precedence model A (RFC-0045): a hosted $NROS_RMW still wins, NULL or "" means "no selector", and a selector that names no registered backend is an error rather than a fallback.

The C surface needed this most. Its open path (nros::internals::open_session) never consulted resolve_backend at all — it took registry slot 0 whenever $NROS_RMW was unset, so a second backend registering from an .init_array ctor before main silently won. That is fixed at the source (nros_rmw_cffi::get_vtable resolves once, for every language), and this is how a C image says which one it meant.

Safety

As [rclc_support_init_named], plus: rmw must be a valid NUL-terminated string or NULL.

◆ rclc_support_init_with_locator()

rcl_ret_t rclc_support_init_with_locator ( struct rclc_support_t *  support,
const char *  locator,
uint8_t  domain_id 
)

Initialize the support context with an explicit locator and domain.

What rclc_support_init was before it took rclc's signature: the middleware locator (e.g. "tcp/127.0.0.1:7447", or NULL for the default) and the ROS domain (0 = unset, resolved from the build / environment).

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if support is NULL
  • RCL_RET_ERROR on initialization failure

Safety

  • support must be a valid pointer to a zero-initialized rclc_support_t
  • locator must be a valid null-terminated string or NULL

◆ rclc_support_is_valid()

bool rclc_support_is_valid ( const struct rclc_support_t *  support)

Check if support context is valid (initialized).

Parameters

  • support - Pointer to a support context

Returns

  • true if valid, false if invalid or NULL

◆ rclc_time_add()

struct rclc_time_t rclc_time_add ( struct rclc_time_t  time,
struct rcl_duration_t  duration 
)

Add a duration to a time.

◆ rclc_time_compare()

int rclc_time_compare ( struct rclc_time_t  a,
struct rclc_time_t  b 
)

Compare two times.

◆ rclc_time_from_nanoseconds()

struct rclc_time_t rclc_time_from_nanoseconds ( int64_t  nanoseconds)

Convert nanoseconds to a rclc_time_t structure.

◆ rclc_time_sub()

struct rclc_time_t rclc_time_sub ( struct rclc_time_t  time,
struct rcl_duration_t  duration 
)

Subtract a duration from a time.

◆ rclc_time_to_nanoseconds()

int64_t rclc_time_to_nanoseconds ( const struct rclc_time_t *  time)

Convert a rclc_time_t structure to nanoseconds.

◆ rclc_timer_get_period()

uint64_t rclc_timer_get_period ( const struct rcl_timer_t *  timer)

Get the timer period in nanoseconds.

Parameters

  • timer - Pointer to a timer

Returns

  • Period in nanoseconds, or 0 if invalid

◆ rclc_timer_init_on_clock()

rcl_ret_t rclc_timer_init_on_clock ( struct rcl_timer_t *  timer,
const struct rcl_clock_t *  clock,
uint64_t  period_ns,
rclc_timer_callback_with_context_t  callback,
void *  context 
)

Initialize a timer scheduled against clock — rcl's shape (phase-430 W1).

rcl_timer_init(timer, clock, context, period, callback, allocator) takes its rcl_clock_t * immediately after the timer, and so does this: the clock is the second parameter. That is RFC-0089's "C takes rcl's spellings" applied to the ARGUMENT LIST, which is the half of the spelling that survives our different callback contract — <rclc/detail/rcl_compat.h> §4 records why the NAME rcl_timer_init stays refused (rcl hands the callback the time since its last call, we hand it the user's context, so a ported timer callback is a different FUNCTION and taking the name would be a compile-and-differ).

The clock's TYPE selects the schedule, through the one mapping [crate::clock::nros_timer_clock_source]:

  • RCL_STEADY_TIME — identical to [rclc_timer_init_with_context].
  • RCL_ROS_TIME — follows the ROS clock. It stops while a simulator is paused, halves with a bag replayed at 0.5x, and restarts its period on a backwards jump. With no /clock override installed it reads system time, the same fallback rclcpp::Clock has, so a node written for simulation still runs standalone.
  • RCL_SYSTEM_TIME — the wall clock, NTP steps and all.

An UNINITIALIZED clock is REJECTED rather than treated as steady: a timer created on a clock the caller never initialised would silently be a wall timer, which is the confusion this verb exists to remove.

The clock must outlive the timer. Its type is read again by rclc_executor_add_timer, which is where the schedule is chosen; rcl has the same obligation and states it the same way.

Parameters

  • timer - Pointer to a zero-initialized timer
  • clock - Pointer to an initialized clock (must NOT be NULL — the clock-less form is [rclc_timer_init_with_context])
  • period_ns - Timer period in nanoseconds
  • callback - Callback function to invoke when timer fires
  • context - User context pointer passed to callback (can be NULL)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL, the period is 0, or the clock names no schedule (uninitialized clock type)
  • RCL_RET_NOT_INIT if the clock is not initialized

Safety

  • All required pointers must be valid
  • callback must be a valid function pointer
  • clock must remain valid for as long as the timer is registered

◆ rclc_timer_init_with_context()

rcl_ret_t rclc_timer_init_with_context ( struct rcl_timer_t *  timer,
uint64_t  period_ns,
rclc_timer_callback_with_context_t  callback,
void *  context 
)

Initialize a WALL timer — the clock-less case (phase-430 W1).

phase-492 W1.b: this was spelled rcl_timer_init, which is rcl's name for a different contract (<rclc/detail/rcl_compat.h> §4), and took the support as a validity witness it never otherwise read. It takes rclc's _with_context spelling — the callback gets the caller's context — and no witness: the timer belongs to no node and no session until rclc_executor_add_timer, which is where the executor is checked. So a C component the generated entry hosts, which has no support, creates timers like any other caller.

The timer is scheduled against the executor's monotonic spin delta, which is what every wall-timer caller has always got and is what rclcpp spells create_wall_timer: a paused simulator does not pause it. For a timer that follows ROS time — a bag replay, a simulator's /clock — use [rclc_timer_init_on_clock], which takes the clock in the position rcl_timer_init puts it.

Parameters

  • timer - Pointer to a zero-initialized timer
  • period_ns - Timer period in nanoseconds
  • callback - Callback function to invoke when timer fires
  • context - User context pointer passed to callback (can be NULL)

Returns

  • RCL_RET_OK on success
  • RCL_RET_INVALID_ARGUMENT if any required pointer is NULL or period is 0

Safety

  • All required pointers must be valid
  • callback must be a valid function pointer

◆ rclc_timer_is_valid()

bool rclc_timer_is_valid ( const struct rcl_timer_t *  timer)

Check if timer is valid (initialized and not shutdown).

Parameters

  • timer - Pointer to a timer

Returns

  • true if valid, false if invalid or NULL

◆ rclc_trace_set_take()

void rclc_trace_set_take ( uint8_t  handle,
bool  on,
int32_t  stamp_offset 
)

phase-474 I3 – trace each sample TAKEN by the subscription in handle (its slot index: the handle its register event carries), or stop.

A take is marker 25 (handle << 24 | take seq), emitted before the callback's start (18). With stamp_offset >= 0 it is followed by 26/27, the sample's stamp.sec / stamp.nanosec read at that byte of the serialized sample, encapsulation header included (4 for a type that starts with a Header or a builtin_interfaces/Time stamp). A negative stamp_offset emits no stamp on the C/C++ paths, which carry no type. Overrides CONFIG_NROS_TRACE_TAKES for this slot.

No-op unless the crate was built with trace-callbacks.

◆ rclc_trace_set_timer_every()

void rclc_trace_set_timer_every ( uint8_t  handle,
uint16_t  every 
)

phase-474 I3 – trace one tick in every of the timer in handle (its slot index): 1 = every tick, 0 = none. Overrides CONFIG_NROS_TRACE_TIMER_EVERY for this slot; the first tick after the call is traced. A 30 Hz tick whose jitter is the measurement can stay whole while the rest are thinned to fit a RAM trace window.

No-op unless the crate was built with trace-callbacks.

◆ rclc_wake_state_get_zero_initialized()

struct rclc_wake_state_t rclc_wake_state_get_zero_initialized ( void  )

Phase 122.3.c.6.e — zero-initialise a wake-state slot.

Variable Documentation

◆ NROS_TRANSPORT_OPS_ABI_VERSION_V1

const uint32_t NROS_TRANSPORT_OPS_ABI_VERSION_V1
extern

Phase 115.A.2 — current ABI version of [nros_transport_ops_t].

C / C++ callers MUST fill in ops.abi_version = NROS_TRANSPORT_OPS_ABI_VERSION_V1 before passing the struct to [rclc_set_custom_transport]. Mismatched values are rejected with RCL_RET_ERROR (mapped from TransportError::IncompatibleAbi); cffi consumers see NROS_RMW_RET_INCOMPATIBLE_ABI.

◆ RCLC_QOS_DEFAULT

const struct rclc_qos_t RCLC_QOS_DEFAULT
extern

Default QoS profile (matches rmw_qos_profile_default).

◆ RCLC_QOS_SENSOR_DATA

const struct rclc_qos_t RCLC_QOS_SENSOR_DATA
extern

Sensor data QoS profile (best effort, small depth).

◆ RCLC_QOS_SERVICES

const struct rclc_qos_t RCLC_QOS_SERVICES
extern

Services QoS profile (reliable).