diff --git a/rcl/include/rcl/graph.h b/rcl/include/rcl/graph.h
index 8fb9f97a3..dfcd3cf68 100644
--- a/rcl/include/rcl/graph.h
+++ b/rcl/include/rcl/graph.h
@@ -292,6 +292,37 @@ rcl_get_service_names_and_types(
rcl_allocator_t * allocator,
rcl_names_and_types_t * service_names_and_types);
+/// Initialize a rcl_names_and_types_t object.
+/**
+ * This function initializes the string array for the names and allocates space
+ * for all the string arrays for the types according to the given size, but
+ * it does not initialize the string array for each set of types.
+ * However, the string arrays for each set of types is zero initialized.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | Yes
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \param[inout] names_and_types object to be initialized
+ * \param[in] size the number of names and sets of types to be stored
+ * \param[in] allocator to be used to allocate and deallocate memory
+ * \returns `RCL_RET_OK` on success, or
+ * \returns `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or
+ * \returns `RCL_BAD_ALLOC` if memory allocation fails, or
+ * \returns `RCL_RET_ERROR` when an unspecified error occurs.
+ */
+RCL_PUBLIC
+RCL_WARN_UNUSED
+rcl_ret_t
+rcl_names_and_types_init(
+ rcl_names_and_types_t * names_and_types,
+ size_t size,
+ rcl_allocator_t * allocator);
+
/// Finalize a rcl_names_and_types_t object.
/**
* The object is populated when given to one of the rcl_get_*_names_and_types()
diff --git a/rcl/src/rcl/graph.c b/rcl/src/rcl/graph.c
index d41df2529..574a7d0f2 100644
--- a/rcl/src/rcl/graph.c
+++ b/rcl/src/rcl/graph.c
@@ -193,6 +193,17 @@ rcl_get_service_names_and_types(
return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
}
+rcl_ret_t
+rcl_names_and_types_init(
+ rcl_names_and_types_t * names_and_types,
+ size_t size,
+ rcl_allocator_t * allocator)
+{
+ RCL_CHECK_ARGUMENT_FOR_NULL(names_and_types, RCL_RET_INVALID_ARGUMENT);
+ rmw_ret_t rmw_ret = rmw_names_and_types_init(names_and_types, size, allocator);
+ return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
+}
+
rcl_ret_t
rcl_names_and_types_fini(rcl_names_and_types_t * topic_names_and_types)
{
diff --git a/rcl/test/rcl/test_graph.cpp b/rcl/test/rcl/test_graph.cpp
index 287ee0f2d..4e424ae1b 100644
--- a/rcl/test/rcl/test_graph.cpp
+++ b/rcl/test/rcl/test_graph.cpp
@@ -170,6 +170,41 @@ TEST_F(
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}
+/* Test the rcl_names_and_types_init function.
+ */
+TEST_F(
+ CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
+ test_rcl_names_and_types_init
+) {
+ rcl_ret_t ret;
+ rcl_allocator_t allocator = rcl_get_default_allocator();
+ rcl_names_and_types_t nat = rcl_get_zero_initialized_names_and_types();
+ // invalid names and types
+ ret = rcl_names_and_types_init(nullptr, 10, &allocator);
+ EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
+ rcl_reset_error();
+ // invalid allocator
+ ret = rcl_names_and_types_init(&nat, 10, nullptr);
+ EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str;
+ rcl_reset_error();
+ // zero size
+ ret = rcl_names_and_types_init(&nat, 0, &allocator);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ EXPECT_EQ(nat.names.size, 0u);
+ ret = rcl_names_and_types_fini(&nat);
+ ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ // non-zero size
+ size_t num_names = 10u;
+ ret = rcl_names_and_types_init(&nat, num_names, &allocator);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+ EXPECT_EQ(nat.names.size, num_names);
+ for (size_t i = 0; i < num_names; i++) {
+ EXPECT_EQ(nat.types[i].size, 0u);
+ }
+ ret = rcl_names_and_types_fini(&nat);
+ EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
+}
+
/* Test the rcl_count_publishers function.
*
* This does not test content the response.