diff --git a/examples/minimal_client_service/src/minimal_service.rs b/examples/minimal_client_service/src/minimal_service.rs index b4149c817..312fc03e8 100644 --- a/examples/minimal_client_service/src/minimal_service.rs +++ b/examples/minimal_client_service/src/minimal_service.rs @@ -3,7 +3,6 @@ use std::env; use anyhow::{Error, Result}; fn handle_service( - _request_header: &rclrs::rmw_request_id_t, request: example_interfaces::srv::AddTwoInts_Request, ) -> example_interfaces::srv::AddTwoInts_Response { println!("request: {} + {}", request.a, request.b); @@ -17,8 +16,8 @@ fn main() -> Result<(), Error> { let node = rclrs::create_node(&context, "minimal_service")?; - let _server = node - .create_service::("add_two_ints", handle_service)?; + let _server = + node.create_service::("add_two_ints", handle_service)?; println!("Starting server"); rclrs::spin(node).map_err(|err| err.into()) diff --git a/rclrs/src/node.rs b/rclrs/src/node.rs index 87702ab0f..a335d2156 100644 --- a/rclrs/src/node.rs +++ b/rclrs/src/node.rs @@ -263,14 +263,32 @@ impl Node { /// /// [1]: crate::Service // TODO: make service's lifetime depend on node's lifetime - pub fn create_service( + pub fn create_service( &self, topic: &str, - callback: F, + mut callback: impl FnMut(T::Request) -> T::Response + 'static + Send, + ) -> Result>, RclrsError> + where + T: rosidl_runtime_rs::Service, + { + let callback = + move |_request_header: &rmw_request_id_t, request: T::Request| callback(request); + self.create_service_with_header(topic, callback) + } + + /// Creates a [`Service`][1]. Same as [`create_service`][2] but the callback + /// also has access to the ID of the service request. + /// + /// [1]: crate::Service + /// [2]: Self::create_service + // TODO: make service's lifetime depend on node's lifetime + pub fn create_service_with_header( + &self, + topic: &str, + callback: impl FnMut(&rmw_request_id_t, T::Request) -> T::Response + 'static + Send, ) -> Result>, RclrsError> where T: rosidl_runtime_rs::Service, - F: Fn(&rmw_request_id_t, T::Request) -> T::Response + 'static + Send, { let service = Arc::new(Service::::new( Arc::clone(&self.rcl_node_mtx), diff --git a/rclrs/src/service.rs b/rclrs/src/service.rs index 8cac799b1..ddbf470c9 100644 --- a/rclrs/src/service.rs +++ b/rclrs/src/service.rs @@ -47,15 +47,17 @@ pub trait ServiceBase: Send + Sync { } type ServiceCallback = - Box Response + 'static + Send>; + Box Response + 'static + Send>; /// Main class responsible for responding to requests sent by ROS clients. /// -/// The only available way to instantiate services is via [`Node::create_service()`][1], this is to -/// ensure that [`Node`][2]s can track all the services that have been created. +/// The only available way to instantiate services is via [`Node::create_service()`][1] and +/// [`Node::create_service_with_header()`][2], this is to +/// ensure that [`Node`][3]s can track all the services that have been created. /// /// [1]: crate::Node::create_service -/// [2]: crate::Node +/// [2]: crate::Node::create_service_with_header +/// [3]: crate::Node pub struct Service where T: rosidl_runtime_rs::Service, @@ -79,7 +81,7 @@ where // [`Node::create_service`], see the struct's documentation for the rationale where T: rosidl_runtime_rs::Service, - F: Fn(&rmw_request_id_t, T::Request) -> T::Response + 'static + Send, + F: FnMut(&rmw_request_id_t, T::Request) -> T::Response + 'static + Send, { // SAFETY: Getting a zero-initialized value is always safe. let mut rcl_service = unsafe { rcl_get_zero_initialized_service() }; diff --git a/rclrs_tests/src/graph_tests.rs b/rclrs_tests/src/graph_tests.rs index 11072e09c..47e456138 100644 --- a/rclrs_tests/src/graph_tests.rs +++ b/rclrs_tests/src/graph_tests.rs @@ -203,7 +203,7 @@ fn test_services() -> Result<(), RclrsError> { let _node_1_empty_service = graph .node1 - .create_service::("graph_test_topic_4", |_, _| srv::Empty_Response { + .create_service::("graph_test_topic_4", |_| srv::Empty_Response { structure_needs_at_least_one_member: 0, })?; let _node_2_empty_client = graph