Skip to content

Commit

Permalink
Copied type_description_interfaces structs (rep2011) (#732)
Browse files Browse the repository at this point in the history
* Copied type_description_interfaces structs

* Also add a github action to check that fingerprints are changed along with copied sources

Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>
  • Loading branch information
emersonknapp authored Mar 29, 2023
1 parent eac4201 commit 8b27b67
Show file tree
Hide file tree
Showing 31 changed files with 5,349 additions and 1 deletion.
33 changes: 33 additions & 0 deletions .github/workflows/check-copied-type-description-sources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Check copied type description sources

on:
pull_request:

jobs:
test_copied_sources_changed_with_fingerprint:
runs-on: ubuntu-latest
outputs:
needs_verification: ${{ steps.needs_verification.outputs.changed }}
steps:
- uses: actions/checkout@v3
- name: Check fingerprint changed
uses: tj-actions/changed-files@v35
id: changed-fingerprint
with:
files: scripts/type_description.fingerprint
- name: Check type description sources changed
uses: tj-actions/changed-files@v35
id: changed-copied-sources
with:
files: |
rosidl_runtime_c/include/rosidl_runtime_c/type_description/**
rosidl_runtime_c/src/type_description/**
rosidl_runtime_cpp/include/rosidl_runtime_cpp/type_description/**
- if: (steps.changed-fingerprint.outputs.any_changed == 'true') && (steps.changed-copied-sources.outputs.any_changed != 'true')
run: |
echo "Fingerprint changed but no copied sources changed"
exit 1
- if: (steps.changed-fingerprint.outputs.any_changed != 'true') && (steps.changed-copied-sources.outputs.any_changed == 'true')
run: |
echo "Copied sources changed but fingerprint not updated"
exit 1
26 changes: 26 additions & 0 deletions rosidl_runtime_c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ find_package(ament_cmake_ros REQUIRED)
find_package(rcutils REQUIRED)
find_package(rosidl_typesupport_interface REQUIRED)

file(GLOB type_description_sources "src/type_description/*.c")
file(GLOB type_description_includes "include/rosidl_runtime_c/type_description/*.h")
add_library(${PROJECT_NAME}
"src/message_type_support.c"
"src/primitives_sequence_functions.c"
Expand All @@ -23,6 +25,7 @@ add_library(${PROJECT_NAME}
"src/string_functions.c"
"src/type_hash.c"
"src/u16string_functions.c"
${type_description_sources}
)
target_include_directories(${PROJECT_NAME} PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
Expand Down Expand Up @@ -60,8 +63,31 @@ if(BUILD_TESTING)
# Give cppcheck hints about macro definitions coming from outside this package
get_target_property(ament_cmake_cppcheck_ADDITIONAL_INCLUDE_DIRS performance_test_fixture::performance_test_fixture
INTERFACE_INCLUDE_DIRECTORIES)

set(AMENT_LINT_AUTO_FILE_EXCLUDE ${type_description_includes} ${type_description_sources})
ament_lint_auto_find_test_dependencies()

# Run specific linters on copied generated code
if(ament_cmake_cppcheck_FOUND)
ament_cppcheck(
TESTNAME "cppcheck_copied_type_description_interfaces"
${type_description_includes} ${type_description_sources})
endif()
if(ament_cmake_cpplint_FOUND)
ament_cpplint(
TESTNAME "cpplint_copied_type_description_interfaces"
# the generated code might contain longer lines for templated types
MAX_LINE_LENGTH 999
${type_description_includes} ${type_description_sources})
endif()
if(ament_cmake_uncrustify_FOUND)
ament_uncrustify(
TESTNAME "uncrustify_copied_type_description_interfaces"
# the generated code might contain longer lines for templated types
MAX_LINE_LENGTH 0
${type_description_includes} ${type_description_sources})
endif()

# For gtest
enable_language(CXX)
# Default to C++17
Expand Down
14 changes: 14 additions & 0 deletions rosidl_runtime_c/docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,17 @@ They are defined for the three main ROS 2 rosidl types:
* Messages (`message_type_support_struct.h`)
* Services (`service_type_support_struct.h`)
* Actions (`action_type_support_struct.h`)

## Type Description Interface Structs

A copy of the output of `rosidl_generator_c` for `type_description_interfaces` messages.
The copy is needed to avoid a circular dependency - `type_description_interfaces` would be used directly for code generation, except as an interface package like any other, it depends on `rosidl_runtime_c` to have its code generated.

Provides base runtime representations of the descriptions of interface types in C.
These can be used in code generation to embed descriptions of types, and can be used for programmatic creation of dynamic types.
The types are renamed so that they do not overlap with `type_description_interfaces` - and can be used in their code generation so that even those messages are self-describing.

Note that end users will typically fetch and use the `type_description_interfaces__msg__TypeDescription` and its members instead of the `rosidl_runtime_c` types.
Functions will be provided in `rcl` that convert between `rosidl_runtime_c__type_description__` and `type_description_interfaces__msg__` types.

See `rosidl/scripts/copy_type_descripiton_generated_sources.bash` for usage and details of how sources are copied, and what modifications are made.
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// DO NOT EDIT MANUALLY - this copied file managed by copy_type_description_generated_sources.bash
// generated from rosidl_generator_c/resource/idl__functions.h.em
// with input from type_description_interfaces:msg/Field.idl
// generated code does not contain a copyright notice

#ifndef ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__FUNCTIONS_H_
#define ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__FUNCTIONS_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdbool.h>
#include <stdlib.h>

#include "rosidl_runtime_c/visibility_control.h"

#include "rosidl_runtime_c/type_description/field__struct.h"

/// Initialize msg/Field message.
/**
* If the init function is called twice for the same message without
* calling fini inbetween previously allocated memory will be leaked.
* \param[in,out] msg The previously allocated message pointer.
* Fields without a default value will not be initialized by this function.
* You might want to call memset(msg, 0, sizeof(
* rosidl_runtime_c__type_description__Field
* )) before or use
* rosidl_runtime_c__type_description__Field__create()
* to allocate and initialize the message.
* \return true if initialization was successful, otherwise false
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__init(rosidl_runtime_c__type_description__Field * msg);

/// Finalize msg/Field message.
/**
* \param[in,out] msg The allocated message pointer.
*/
ROSIDL_GENERATOR_C_PUBLIC
void
rosidl_runtime_c__type_description__Field__fini(rosidl_runtime_c__type_description__Field * msg);

/// Create msg/Field message.
/**
* It allocates the memory for the message, sets the memory to zero, and
* calls
* rosidl_runtime_c__type_description__Field__init().
* \return The pointer to the initialized message if successful,
* otherwise NULL
*/
ROSIDL_GENERATOR_C_PUBLIC
rosidl_runtime_c__type_description__Field *
rosidl_runtime_c__type_description__Field__create();

/// Destroy msg/Field message.
/**
* It calls
* rosidl_runtime_c__type_description__Field__fini()
* and frees the memory of the message.
* \param[in,out] msg The allocated message pointer.
*/
ROSIDL_GENERATOR_C_PUBLIC
void
rosidl_runtime_c__type_description__Field__destroy(rosidl_runtime_c__type_description__Field * msg);

/// Check for msg/Field message equality.
/**
* \param[in] lhs The message on the left hand size of the equality operator.
* \param[in] rhs The message on the right hand size of the equality operator.
* \return true if messages are equal, otherwise false.
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__are_equal(const rosidl_runtime_c__type_description__Field * lhs, const rosidl_runtime_c__type_description__Field * rhs);

/// Copy a msg/Field message.
/**
* This functions performs a deep copy, as opposed to the shallow copy that
* plain assignment yields.
*
* \param[in] input The source message pointer.
* \param[out] output The target message pointer, which must
* have been initialized before calling this function.
* \return true if successful, or false if either pointer is null
* or memory allocation fails.
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__copy(
const rosidl_runtime_c__type_description__Field * input,
rosidl_runtime_c__type_description__Field * output);

/// Initialize array of msg/Field messages.
/**
* It allocates the memory for the number of elements and calls
* rosidl_runtime_c__type_description__Field__init()
* for each element of the array.
* \param[in,out] array The allocated array pointer.
* \param[in] size The size / capacity of the array.
* \return true if initialization was successful, otherwise false
* If the array pointer is valid and the size is zero it is guaranteed
# to return true.
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__Sequence__init(rosidl_runtime_c__type_description__Field__Sequence * array, size_t size);

/// Finalize array of msg/Field messages.
/**
* It calls
* rosidl_runtime_c__type_description__Field__fini()
* for each element of the array and frees the memory for the number of
* elements.
* \param[in,out] array The initialized array pointer.
*/
ROSIDL_GENERATOR_C_PUBLIC
void
rosidl_runtime_c__type_description__Field__Sequence__fini(rosidl_runtime_c__type_description__Field__Sequence * array);

/// Create array of msg/Field messages.
/**
* It allocates the memory for the array and calls
* rosidl_runtime_c__type_description__Field__Sequence__init().
* \param[in] size The size / capacity of the array.
* \return The pointer to the initialized array if successful, otherwise NULL
*/
ROSIDL_GENERATOR_C_PUBLIC
rosidl_runtime_c__type_description__Field__Sequence *
rosidl_runtime_c__type_description__Field__Sequence__create(size_t size);

/// Destroy array of msg/Field messages.
/**
* It calls
* rosidl_runtime_c__type_description__Field__Sequence__fini()
* on the array,
* and frees the memory of the array.
* \param[in,out] array The initialized array pointer.
*/
ROSIDL_GENERATOR_C_PUBLIC
void
rosidl_runtime_c__type_description__Field__Sequence__destroy(rosidl_runtime_c__type_description__Field__Sequence * array);

/// Check for msg/Field message array equality.
/**
* \param[in] lhs The message array on the left hand size of the equality operator.
* \param[in] rhs The message array on the right hand size of the equality operator.
* \return true if message arrays are equal in size and content, otherwise false.
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__Sequence__are_equal(const rosidl_runtime_c__type_description__Field__Sequence * lhs, const rosidl_runtime_c__type_description__Field__Sequence * rhs);

/// Copy an array of msg/Field messages.
/**
* This functions performs a deep copy, as opposed to the shallow copy that
* plain assignment yields.
*
* \param[in] input The source array pointer.
* \param[out] output The target array pointer, which must
* have been initialized before calling this function.
* \return true if successful, or false if either pointer
* is null or memory allocation fails.
*/
ROSIDL_GENERATOR_C_PUBLIC
bool
rosidl_runtime_c__type_description__Field__Sequence__copy(
const rosidl_runtime_c__type_description__Field__Sequence * input,
rosidl_runtime_c__type_description__Field__Sequence * output);

#ifdef __cplusplus
}
#endif

#endif // ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__FUNCTIONS_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// DO NOT EDIT MANUALLY - this copied file managed by copy_type_description_generated_sources.bash
// generated from rosidl_generator_c/resource/idl__struct.h.em
// with input from type_description_interfaces:msg/Field.idl
// generated code does not contain a copyright notice

#ifndef ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__STRUCT_H_
#define ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__STRUCT_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "rosidl_runtime_c/type_hash.h"


// Type Hash for interface
static const rosidl_type_hash_t rosidl_runtime_c__type_description__Field__TYPE_HASH = {1, {
0xc0, 0xb0, 0x13, 0x79, 0xcd, 0x42, 0x26, 0x28,
0x12, 0x85, 0xcc, 0xaf, 0x6b, 0xe4, 0x66, 0x53,
0x96, 0x8f, 0x85, 0x5f, 0x7c, 0x5e, 0x41, 0x61,
0x4f, 0xf5, 0xd7, 0xa8, 0x54, 0xef, 0xef, 0x7c,
}};

// Constants defined in the message

// Include directives for member types
// Member 'name'
// Member 'default_value'
#include "rosidl_runtime_c/string.h"
// Member 'type'
#include "rosidl_runtime_c/type_description/field_type__struct.h"

/// Struct defined in msg/Field in the package type_description_interfaces.
/**
* Represents a single field in a type.
*/
typedef struct rosidl_runtime_c__type_description__Field
{
/// Name of the field.
rosidl_runtime_c__String name;
/// Type of the field, including details about the type like length, nested name, etc.
rosidl_runtime_c__type_description__FieldType type;
/// Literal default value of the field as a string, as it appeared in the original
/// message description file, whether that be .msg/.srv/.action or .idl.
rosidl_runtime_c__String default_value;
} rosidl_runtime_c__type_description__Field;

// Struct for a sequence of rosidl_runtime_c__type_description__Field.
typedef struct rosidl_runtime_c__type_description__Field__Sequence
{
rosidl_runtime_c__type_description__Field * data;
/// The number of valid items in data
size_t size;
/// The number of allocated items in data
size_t capacity;
} rosidl_runtime_c__type_description__Field__Sequence;

#ifdef __cplusplus
}
#endif

#endif // ROSIDL_RUNTIME_C__TYPE_DESCRIPTION__FIELD__STRUCT_H_
Loading

0 comments on commit 8b27b67

Please sign in to comment.