diff --git a/rcl/include/rcl/client.h b/rcl/include/rcl/client.h
index 94290982a..224f74b8c 100644
--- a/rcl/include/rcl/client.h
+++ b/rcl/include/rcl/client.h
@@ -24,6 +24,7 @@ extern "C"
#include "rosidl_runtime_c/service_type_support_struct.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/node.h"
#include "rcl/visibility_control.h"
@@ -461,6 +462,37 @@ RCL_WARN_UNUSED
const rmw_qos_profile_t *
rcl_client_response_subscription_get_actual_qos(const rcl_client_t * client);
+/// Set the on new response callback function for the client.
+/**
+ * This API sets the callback function to be called whenever the
+ * client is notified about a new response.
+ *
+ * \sa rmw_client_set_on_new_response_callback for details about this function.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined
+ *
+ * \param[in] client The client on which to set the callback
+ * \param[in] callback The callback to be called when new responses arrive, may be NULL
+ * \param[in] user_data Given to the callback when called later, may be NULL
+ * \return `RCL_RET_OK` if callback was set to the listener, or
+ * \return `RCL_RET_INVALID_ARGUMENT` if `client` is NULL, or
+ * \return `RCL_RET_UNSUPPORTED` if the API is not implemented in the dds implementation
+ */
+RCL_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_client_set_on_new_response_callback(
+ const rcl_client_t * client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/include/rcl/event.h b/rcl/include/rcl/event.h
index abf4e6386..fea87d782 100644
--- a/rcl/include/rcl/event.h
+++ b/rcl/include/rcl/event.h
@@ -25,6 +25,7 @@ extern "C"
#include
#include "rcl/client.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/publisher.h"
#include "rcl/service.h"
@@ -198,6 +199,37 @@ RCL_PUBLIC
bool
rcl_event_is_valid(const rcl_event_t * event);
+/// Set the callback function for the event.
+/**
+ * This API sets the callback function to be called whenever the
+ * event is notified about a new instance of the event.
+ *
+ * \sa rmw_event_set_callback for more details about this function.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined
+ *
+ * \param[in] event The event on which to set the callback
+ * \param[in] callback The callback to be called when new events occur, may be NULL
+ * \param[in] user_data Given to the callback when called later, may be NULL
+ * \return `RCL_RET_OK` if callback was set to the listener, or
+ * \return `RCL_RET_INVALID_ARGUMENT` if `event` is NULL, or
+ * \return `RCL_RET_UNSUPPORTED` if the API is not implemented in the dds implementation
+ */
+RCL_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_event_set_callback(
+ const rcl_event_t * event,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/include/rcl/event_callback.h b/rcl/include/rcl/event_callback.h
new file mode 100644
index 000000000..9124907ab
--- /dev/null
+++ b/rcl/include/rcl/event_callback.h
@@ -0,0 +1,31 @@
+// Copyright 2021 Open Source Robotics Foundation, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef RCL__EVENT_CALLBACK_H_
+#define RCL__EVENT_CALLBACK_H_
+
+#include "rmw/event_callback_type.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef rmw_event_callback_t rcl_event_callback_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // RCL__EVENT_CALLBACK_H_
diff --git a/rcl/include/rcl/service.h b/rcl/include/rcl/service.h
index b102d14c9..2461bd551 100644
--- a/rcl/include/rcl/service.h
+++ b/rcl/include/rcl/service.h
@@ -24,6 +24,7 @@ extern "C"
#include "rosidl_runtime_c/service_type_support_struct.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/node.h"
#include "rcl/visibility_control.h"
@@ -492,6 +493,37 @@ RCL_WARN_UNUSED
const rmw_qos_profile_t *
rcl_service_response_publisher_get_actual_qos(const rcl_service_t * service);
+/// Set the on new request callback function for the service.
+/**
+ * This API sets the callback function to be called whenever the
+ * service is notified about a new request.
+ *
+ * \sa rmw_service_set_on_new_request_callback for details about this function.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined
+ *
+ * \param[in] service The service on which to set the callback
+ * \param[in] callback The callback to be called when new requests arrive, may be NULL
+ * \param[in] user_data Given to the callback when called later, may be NULL
+ * \return `RCL_RET_OK` if callback was set to the listener, or
+ * \return `RCL_RET_INVALID_ARGUMENT` if `service` is NULL, or
+ * \return `RCL_RET_UNSUPPORTED` if the API is not implemented in the dds implementation
+ */
+RCL_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_service_set_on_new_request_callback(
+ const rcl_service_t * service,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/include/rcl/subscription.h b/rcl/include/rcl/subscription.h
index 09d6e6bc4..121949999 100644
--- a/rcl/include/rcl/subscription.h
+++ b/rcl/include/rcl/subscription.h
@@ -24,6 +24,7 @@ extern "C"
#include "rosidl_runtime_c/message_type_support_struct.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/node.h"
#include "rcl/visibility_control.h"
@@ -611,6 +612,38 @@ RCL_PUBLIC
bool
rcl_subscription_can_loan_messages(const rcl_subscription_t * subscription);
+/// Set the on new message callback function for the subscription.
+/**
+ * This API sets the callback function to be called whenever the
+ * subscription is notified about a new message.
+ *
+ * \sa rmw_subscription_set_on_new_message_callback for details about this
+ * function.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | Yes
+ * Uses Atomics | Maybe [1]
+ * Lock-Free | Maybe [1]
+ * [1] rmw implementation defined
+ *
+ * \param[in] subscription The subscription on which to set the callback
+ * \param[in] callback The callback to be called when new messages arrive, may be NULL
+ * \param[in] user_data Given to the callback when called later, may be NULL
+ * \return `RCL_RET_OK` if successful, or
+ * \return `RCL_RET_INVALID_ARGUMENT` if `subscription` is NULL, or
+ * \return `RCL_RET_UNSUPPORTED` if the API is not implemented in the dds implementation
+ */
+RCL_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_subscription_set_on_new_message_callback(
+ const rcl_subscription_t * subscription,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/src/rcl/client.c b/rcl/src/rcl/client.c
index bd38efa7a..432948d59 100644
--- a/rcl/src/rcl/client.c
+++ b/rcl/src/rcl/client.c
@@ -327,6 +327,24 @@ rcl_client_response_subscription_get_actual_qos(const rcl_client_t * client)
}
return &client->impl->actual_response_subscription_qos;
}
+
+rcl_ret_t
+rcl_client_set_on_new_response_callback(
+ const rcl_client_t * client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_client_is_valid(client)) {
+ // error state already set
+ return RCL_RET_INVALID_ARGUMENT;
+ }
+
+ return rmw_client_set_on_new_response_callback(
+ client->impl->rmw_handle,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/src/rcl/event.c b/rcl/src/rcl/event.c
index c79c60ce6..6196442d1 100644
--- a/rcl/src/rcl/event.c
+++ b/rcl/src/rcl/event.c
@@ -218,6 +218,23 @@ rcl_event_is_valid(const rcl_event_t * event)
return true;
}
+rcl_ret_t
+rcl_event_set_callback(
+ const rcl_event_t * event,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_event_is_valid(event)) {
+ // error state already set
+ return RCL_RET_INVALID_ARGUMENT;
+ }
+
+ return rmw_event_set_callback(
+ &event->impl->rmw_handle,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/src/rcl/service.c b/rcl/src/rcl/service.c
index 42222b996..e1bdb0174 100644
--- a/rcl/src/rcl/service.c
+++ b/rcl/src/rcl/service.c
@@ -346,6 +346,23 @@ rcl_service_response_publisher_get_actual_qos(const rcl_service_t * service)
return &service->impl->actual_response_publisher_qos;
}
+rcl_ret_t
+rcl_service_set_on_new_request_callback(
+ const rcl_service_t * service,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_service_is_valid(service)) {
+ // error state already set
+ return RCL_RET_INVALID_ARGUMENT;
+ }
+
+ return rmw_service_set_on_new_request_callback(
+ service->impl->rmw_handle,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl/src/rcl/subscription.c b/rcl/src/rcl/subscription.c
index d92fe21a4..32c3ca767 100644
--- a/rcl/src/rcl/subscription.c
+++ b/rcl/src/rcl/subscription.c
@@ -445,6 +445,23 @@ rcl_subscription_can_loan_messages(const rcl_subscription_t * subscription)
return subscription->impl->rmw_handle->can_loan_messages;
}
+rcl_ret_t
+rcl_subscription_set_on_new_message_callback(
+ const rcl_subscription_t * subscription,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_subscription_is_valid(subscription)) {
+ // error state already set
+ return RCL_RET_INVALID_ARGUMENT;
+ }
+
+ return rmw_subscription_set_on_new_message_callback(
+ subscription->impl->rmw_handle,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl_action/include/rcl_action/action_client.h b/rcl_action/include/rcl_action/action_client.h
index 7fdf6df78..b686b65f1 100644
--- a/rcl_action/include/rcl_action/action_client.h
+++ b/rcl_action/include/rcl_action/action_client.h
@@ -22,6 +22,7 @@ extern "C"
#include "rcl_action/types.h"
#include "rcl_action/visibility_control.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/node.h"
@@ -741,6 +742,46 @@ bool
rcl_action_client_is_valid(
const rcl_action_client_t * action_client);
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_client_set_goal_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_client_set_cancel_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_client_set_result_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_client_set_feedback_subscription_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_client_set_status_subscription_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl_action/include/rcl_action/action_server.h b/rcl_action/include/rcl_action/action_server.h
index d0d9a8e3a..eb4f95ce9 100644
--- a/rcl_action/include/rcl_action/action_server.h
+++ b/rcl_action/include/rcl_action/action_server.h
@@ -23,6 +23,7 @@ extern "C"
#include "rcl_action/goal_handle.h"
#include "rcl_action/types.h"
#include "rcl_action/visibility_control.h"
+#include "rcl/event_callback.h"
#include "rcl/macros.h"
#include "rcl/node.h"
#include "rcl/time.h"
@@ -930,6 +931,30 @@ RCL_WARN_UNUSED
bool
rcl_action_server_is_valid_except_context(const rcl_action_server_t * action_server);
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_goal_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_cancel_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_result_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl_action/src/rcl_action/action_client.c b/rcl_action/src/rcl_action/action_client.c
index a03a61ec3..d999f1e01 100644
--- a/rcl_action/src/rcl_action/action_client.c
+++ b/rcl_action/src/rcl_action/action_client.c
@@ -649,6 +649,86 @@ rcl_action_client_wait_set_get_entities_ready(
return RCL_RET_OK;
}
+rcl_ret_t
+rcl_action_client_set_goal_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_client_is_valid(action_client)) {
+ return RCL_RET_ACTION_CLIENT_INVALID;
+ }
+
+ return rcl_client_set_on_new_response_callback(
+ &action_client->impl->goal_client,
+ callback,
+ user_data);
+}
+
+rcl_ret_t
+rcl_action_client_set_cancel_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_client_is_valid(action_client)) {
+ return RCL_RET_ACTION_CLIENT_INVALID;
+ }
+
+ return rcl_client_set_on_new_response_callback(
+ &action_client->impl->cancel_client,
+ callback,
+ user_data);
+}
+
+rcl_ret_t
+rcl_action_client_set_result_client_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_client_is_valid(action_client)) {
+ return RCL_RET_ACTION_CLIENT_INVALID;
+ }
+
+ return rcl_client_set_on_new_response_callback(
+ &action_client->impl->result_client,
+ callback,
+ user_data);
+}
+
+rcl_ret_t
+rcl_action_client_set_feedback_subscription_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_client_is_valid(action_client)) {
+ return RCL_RET_ACTION_CLIENT_INVALID;
+ }
+
+ return rcl_subscription_set_on_new_message_callback(
+ &action_client->impl->feedback_subscription,
+ callback,
+ user_data);
+}
+
+rcl_ret_t
+rcl_action_client_set_status_subscription_callback(
+ const rcl_action_client_t * action_client,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_client_is_valid(action_client)) {
+ return RCL_RET_ACTION_CLIENT_INVALID;
+ }
+
+ return rcl_subscription_set_on_new_message_callback(
+ &action_client->impl->status_subscription,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/rcl_action/src/rcl_action/action_server.c b/rcl_action/src/rcl_action/action_server.c
index a5b6dbde4..63580c40f 100644
--- a/rcl_action/src/rcl_action/action_server.c
+++ b/rcl_action/src/rcl_action/action_server.c
@@ -1054,6 +1054,60 @@ rcl_action_server_wait_set_get_entities_ready(
return RCL_RET_OK;
}
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_goal_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_server_is_valid_except_context(action_server)) {
+ return RCL_RET_ACTION_SERVER_INVALID;
+ }
+
+ return rcl_service_set_on_new_request_callback(
+ &action_server->impl->goal_service,
+ callback,
+ user_data);
+}
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_result_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_server_is_valid_except_context(action_server)) {
+ return RCL_RET_ACTION_SERVER_INVALID;
+ }
+
+ return rcl_service_set_on_new_request_callback(
+ &action_server->impl->result_service,
+ callback,
+ user_data);
+}
+
+RCL_ACTION_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_action_server_set_cancel_service_callback(
+ const rcl_action_server_t * action_server,
+ rcl_event_callback_t callback,
+ const void * user_data)
+{
+ if (!rcl_action_server_is_valid_except_context(action_server)) {
+ return RCL_RET_ACTION_SERVER_INVALID;
+ }
+
+ return rcl_service_set_on_new_request_callback(
+ &action_server->impl->cancel_service,
+ callback,
+ user_data);
+}
+
#ifdef __cplusplus
}
#endif