Skip to content

Commit

Permalink
Add empty raw sources
Browse files Browse the repository at this point in the history
Signed-off-by: Emerson Knapp <emerson.b.knapp@gmail.com>
  • Loading branch information
emersonknapp committed Mar 29, 2023
1 parent 91962ba commit dc3d464
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 64 deletions.
84 changes: 43 additions & 41 deletions rosidl_generator_c/resource/idl__description.c.em
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
@{
from rosidl_generator_c import escape_string
from rosidl_generator_type_description import extract_subinterface
from rosidl_generator_type_description import RAW_SOURCE_VAR
from rosidl_generator_type_description import TYPE_DESCRIPTION_VAR
from rosidl_parser.definition import Action
from rosidl_parser.definition import Service
from rosidl_pycommon import convert_camel_case_to_lower_case_underscore
Expand Down Expand Up @@ -48,91 +50,91 @@ for action in content.get_elements_of_type(Action):
full_type_descriptions.append(extract_subinterface(get_result_service, 'event_message'))

full_type_descriptions.append(extract_subinterface(type_description_msg, 'feedback_message'))

def typename_to_c(typename):
return typename.replace('/', '__')

def static_seq(varname, values):
"""Statically define a runtime Sequence or String type."""
if values:
return f'{{{varname}, {len(values)}, {len(values)}}}'
return '{NULL, 0, 0}'
}@

#include "@(include_base)__struct.h"

#define STATIC_SEQ(x) {x, sizeof(x), sizeof(x)}
#define NULL_SEQ {NULL, 0, 0}

// Declare and define all type names, field names, and default values
@[for itype_description in all_type_descriptions]@
@{ td_typename = itype_description['type_name'].replace('/', '__') }@
static char @(td_typename)__TYPE_NAME[] = "@(itype_description['type_name'])";
@{
td_c_typename = typename_to_c(itype_description['type_name'])
}@
static char @(td_c_typename)__TYPE_NAME[] = "@(itype_description['type_name'])";
@[ for field in itype_description['fields']]@
static char @(td_typename)__FIELD_NAME__@(field['name'])[] = "@(field['name'])";
static char @(td_c_typename)__FIELD_NAME__@(field['name'])[] = "@(field['name'])";
@[ if field['default_value']]@
static char @(td_typename)__DEFAULT_VALUE__@(field['name'])[] = "@(escape_string(field['default_value']))";
static char @(td_c_typename)__DEFAULT_VALUE__@(field['name'])[] = "@(escape_string(field['default_value']))";
@[ end if]@
@[ end for]@

@[end for]@
@
/// Define all arrays of Fields
@[for itype_description in all_type_descriptions]@
@{ td_typename = itype_description['type_name'].replace('/', '__') }@
@{
td_c_typename = typename_to_c(itype_description['type_name'])
}@
@[ if itype_description['fields']]@
static rosidl_runtime_c__type_description__Field @(td_typename)__FIELDS[] = {
static rosidl_runtime_c__type_description__Field @(td_c_typename)__FIELDS[] = {
@[ for field in itype_description['fields']]@
{
STATIC_SEQ(@(td_typename)__FIELD_NAME__@(field['name'])),
@(static_seq(f"{td_c_typename}__FIELD_NAME__{field['name']}", field['name'])),
{
@(field['type']['type_id']), // TODO(ek) should this be named to FieldType const, or is value ok?
@(field['type']['capacity']),
@(field['type']['string_capacity']),
@[ if field['type']['nested_type_name']]@
STATIC_SEQ(@(field['type']['nested_type_name'].replace('/', '__'))__TYPE_NAME),
@[ else]@
NULL_SEQ,
@[ end if]@
@(static_seq(f"{typename_to_c(field['type']['nested_type_name'])}__TYPE_NAME", field['type']['nested_type_name'])),
},
@[ if field['default_value']]@
STATIC_SEQ(@(td_typename)__DEFAULT_VALUE__@(field['name'])),
@[ else]@
NULL_SEQ,
@[ end if]@
@(static_seq(f"{td_c_typename}__DEFAULT_VALUE__{field['name']}", field['default_value'])),
},
@[ end for]@
};
@[ end if]@
@[end for]@
@
/// Define all IndividualTypeDescriptions
@[for itype_description in all_type_descriptions]@
@{ td_typename = itype_description['type_name'].replace('/', '__') }@
@{
td_c_typename = typename_to_c(itype_description['type_name'])
}@

static const rosidl_runtime_c__type_description__IndividualTypeDescription @(td_typename)__INDIVIDUAL_TYPE_DESCRIPTION = {
STATIC_SEQ(@(td_typename)__TYPE_NAME),
@[ if itype_description['fields']]@
STATIC_SEQ(@(td_typename)__FIELDS),
@[ else]@
NULL_SEQ,
@[ end if]@
static const rosidl_runtime_c__type_description__IndividualTypeDescription @(td_c_typename)__INDIVIDUAL_TYPE_DESCRIPTION = {
@(static_seq(f'{td_c_typename}__TYPE_NAME', itype_description['type_name'])),
@(static_seq(f'{td_c_typename}__FIELDS', itype_description['fields'])),
};
@[end for]@
@
/// Define exported TypeDescriptions

/// Define exported TypeDescriptions and TypeSources
@[for msg in full_type_descriptions]@
@{
td_var_name = msg['type_description']['type_name'].replace('/', '__')
td_typename = msg['type_description']['type_name']
td_c_typename = typename_to_c(td_typename)
ref_tds = msg['referenced_type_descriptions']
}@
@[ if ref_tds]@
static rosidl_runtime_c__type_description__IndividualTypeDescription @(td_var_name)__REFERENCED_TYPE_DESCRIPTIONS[] = {
static rosidl_runtime_c__type_description__IndividualTypeDescription @(td_c_typename)__REFERENCED_TYPE_DESCRIPTIONS[] = {
@[ for ref_td in ref_tds]@
@(ref_td['type_name'].replace('/', '__'))__INDIVIDUAL_TYPE_DESCRIPTION,
@(typename_to_c(ref_td['type_name']))__INDIVIDUAL_TYPE_DESCRIPTION,
@[ end for]@
};
@[ end if]@
const rosidl_runtime_c__type_description__TypeDescription @(td_var_name)__TYPE_DESCRIPTION = {
@(td_var_name)__INDIVIDUAL_TYPE_DESCRIPTION,
@[ if ref_tds]@
STATIC_SEQ(@(td_var_name)__REFERENCED_TYPE_DESCRIPTIONS),
@[ else]@
NULL_SEQ,
@[ end if]@
const rosidl_runtime_c__type_description__TypeDescription @(td_c_typename)__@(TYPE_DESCRIPTION_VAR) = {
@(td_c_typename)__INDIVIDUAL_TYPE_DESCRIPTION,
@(static_seq(f'{td_c_typename}__REFERENCED_TYPE_DESCRIPTIONS', ref_tds)),
};
// NOTE: currently filling only empty sequence
const rosidl_runtime_c__type_description__TypeSource__Sequence @(td_c_typename)__@(RAW_SOURCE_VAR) = @(static_seq(None, ''));
@[end for]@
34 changes: 22 additions & 12 deletions rosidl_generator_c/resource/idl__struct.h.em
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@{
from rosidl_generator_c import idl_structure_type_to_c_typename
from rosidl_generator_c import type_hash_to_c_definition
from rosidl_generator_type_description import RAW_SOURCE_VAR
from rosidl_generator_type_description import TYPE_DESCRIPTION_VAR
from rosidl_generator_type_description import TYPE_HASH_VAR
from rosidl_pycommon import convert_camel_case_to_lower_case_underscore
Expand All @@ -38,6 +39,7 @@ extern "C"
#include <stdint.h>

#include "rosidl_runtime_c/type_description/type_description__struct.h"
#include "rosidl_runtime_c/type_description/type_source__struct.h"
#include "rosidl_runtime_c/type_hash.h"

@#######################################################################
Expand All @@ -63,11 +65,13 @@ TEMPLATE(
from rosidl_parser.definition import Service
}@
@[for service in content.get_elements_of_type(Service)]@
@{ srv_var = idl_structure_type_to_c_typename(service.namespaced_type) }@
@{ srv_typename = idl_structure_type_to_c_typename(service.namespaced_type) }@

extern const rosidl_runtime_c__type_description__TypeDescription @(srv_var)__@(TYPE_DESCRIPTION_VAR);
static const rosidl_type_hash_t @(srv_typename)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['service']));

static const rosidl_type_hash_t @(srv_var)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['service']));
extern const rosidl_runtime_c__type_description__TypeDescription @(srv_typename)__@(TYPE_DESCRIPTION_VAR);

extern const rosidl_runtime_c__type_description__TypeSource__Sequence @(srv_typename)__@(RAW_SOURCE_VAR);

@{
TEMPLATE(
Expand Down Expand Up @@ -103,14 +107,16 @@ from rosidl_parser.definition import Action
}@
@[for action in content.get_elements_of_type(Action)]@
@{
action_var = idl_structure_type_to_c_typename(action.namespaced_type)
send_goal_srv_var = idl_structure_type_to_c_typename(action.send_goal_service.namespaced_type)
get_result_srv_var = idl_structure_type_to_c_typename(action.get_result_service.namespaced_type)
action_typename = idl_structure_type_to_c_typename(action.namespaced_type)
send_goal_srv_typename = idl_structure_type_to_c_typename(action.send_goal_service.namespaced_type)
get_result_srv_typename = idl_structure_type_to_c_typename(action.get_result_service.namespaced_type)
}@

extern const rosidl_runtime_c__type_description__TypeDescription @(action_var)__@(TYPE_DESCRIPTION_VAR);
static const rosidl_type_hash_t @(action_typename)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['action']));

extern const rosidl_runtime_c__type_description__TypeDescription @(action_typename)__@(TYPE_DESCRIPTION_VAR);

static const rosidl_type_hash_t @(action_var)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['action']));
extern const rosidl_runtime_c__type_description__TypeSource__Sequence @(action_typename)__@(RAW_SOURCE_VAR);

@{
TEMPLATE(
Expand All @@ -136,9 +142,11 @@ TEMPLATE(
type_hash=type_hash['feedback'])
}@

extern const rosidl_runtime_c__type_description__TypeDescription @(send_goal_srv_var)__@(TYPE_DESCRIPTION_VAR);
static const rosidl_type_hash_t @(send_goal_srv_typename)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['send_goal_service']['service']));

static const rosidl_type_hash_t @(send_goal_srv_var)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['send_goal_service']['service']));
extern const rosidl_runtime_c__type_description__TypeDescription @(send_goal_srv_typename)__@(TYPE_DESCRIPTION_VAR);

extern const rosidl_runtime_c__type_description__TypeSource__Sequence @(send_goal_srv_typename)__@(RAW_SOURCE_VAR);

@{
TEMPLATE(
Expand All @@ -164,9 +172,11 @@ TEMPLATE(
type_hash=type_hash['send_goal_service']['event_message'])
}@

static const rosidl_type_hash_t @(get_result_srv_var)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['get_result_service']['service']));
static const rosidl_type_hash_t @(get_result_srv_typename)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['get_result_service']['service']));

extern const rosidl_runtime_c__type_description__TypeDescription @(get_result_srv_typename)__@(TYPE_DESCRIPTION_VAR);

extern const rosidl_runtime_c__type_description__TypeDescription @(get_result_srv_var)__@(TYPE_DESCRIPTION_VAR);
extern const rosidl_runtime_c__type_description__TypeSource__Sequence @(get_result_srv_typename)__@(RAW_SOURCE_VAR);

@{
TEMPLATE(
Expand Down
27 changes: 16 additions & 11 deletions rosidl_generator_c/resource/msg__struct.h.em
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ from rosidl_generator_c import idl_structure_type_to_c_typename
from rosidl_generator_c import interface_path_to_string
from rosidl_generator_c import type_hash_to_c_definition
from rosidl_generator_c import value_to_c
from rosidl_generator_type_description import RAW_SOURCE_VAR
from rosidl_generator_type_description import TYPE_DESCRIPTION_VAR
from rosidl_generator_type_description import TYPE_HASH_VAR
}@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Collect necessary include directives for all members
@{
from collections import OrderedDict
message_typename = idl_structure_type_to_c_typename(message.structure.namespaced_type)
includes = OrderedDict()
for member in message.structure.members:
if isinstance(member.type, AbstractSequence) and isinstance(member.type.value_type, BasicType):
Expand Down Expand Up @@ -66,10 +68,13 @@ for member in message.structure.members:

@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Type Hash for interface
static const rosidl_type_hash_t @(idl_structure_type_to_c_typename(message.structure.namespaced_type))__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['message']));
static const rosidl_type_hash_t @(message_typename)__@(TYPE_HASH_VAR) = @(type_hash_to_c_definition(type_hash['message']));

/// Type Description for interface
extern const rosidl_runtime_c__type_description__TypeDescription @(idl_structure_type_to_c_typename(message.structure.namespaced_type))__@(TYPE_DESCRIPTION_VAR);
extern const rosidl_runtime_c__type_description__TypeDescription @(message_typename)__@(TYPE_DESCRIPTION_VAR);
/// Raw sources defining the type description
extern const rosidl_runtime_c__type_description__TypeSource__Sequence @(message_typename)__@(RAW_SOURCE_VAR);

// Constants defined in the message
@[for constant in message.constants]@
Expand All @@ -93,15 +98,15 @@ extern const rosidl_runtime_c__type_description__TypeDescription @(idl_structure
)]@
enum
{
@(idl_structure_type_to_c_typename(message.structure.namespaced_type))__@(constant.name) = @(value_to_c(constant.type, constant.value))
@(message_typename)__@(constant.name) = @(value_to_c(constant.type, constant.value))
};
@[ elif constant.type.typename in (*FLOATING_POINT_TYPES, BOOLEAN_TYPE)]@
static const @(basetype_to_c(constant.type)) @(idl_structure_type_to_c_typename(message.structure.namespaced_type))__@(constant.name) = @(value_to_c(constant.type, constant.value));
static const @(basetype_to_c(constant.type)) @(message_typename)__@(constant.name) = @(value_to_c(constant.type, constant.value));
@[ else]@
@{assert False, 'Unhandled basic type: ' + str(constant.type)}@
@[ end if]@
@[ elif isinstance(constant.type, AbstractString)]@
static const char * const @(idl_structure_type_to_c_typename(message.structure.namespaced_type))__@(constant.name) = @(value_to_c(constant.type, constant.value));
static const char * const @(message_typename)__@(constant.name) = @(value_to_c(constant.type, constant.value));
@[ end if]@
@[end for]@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Expand Down Expand Up @@ -134,15 +139,15 @@ for member in message.structure.members:
if isinstance(type_, BoundedSequence):
upper_bounds.append((
member.name,
'%s__%s__MAX_SIZE' % (idl_structure_type_to_c_typename(message.structure.namespaced_type), member.name),
'%s__%s__MAX_SIZE' % (message_typename, member.name),
type_.maximum_size,
))
if isinstance(type_, AbstractNestedType):
type_ = type_.value_type
if isinstance(type_, AbstractGenericString) and type_.has_maximum_size():
upper_bounds.append((
member.name,
'%s__%s__MAX_STRING_SIZE' % (idl_structure_type_to_c_typename(message.structure.namespaced_type), member.name),
'%s__%s__MAX_STRING_SIZE' % (message_typename, member.name),
type_.maximum_size,
))
}@
Expand Down Expand Up @@ -173,7 +178,7 @@ enum
@[ end for]@
*/
@[end if]@
typedef struct @(idl_structure_type_to_c_typename(message.structure.namespaced_type))
typedef struct @(message_typename)
{
@[for member in message.structure.members]@
@[ for line in member.get_comment_lines()]@
Expand All @@ -185,14 +190,14 @@ typedef struct @(idl_structure_type_to_c_typename(message.structure.namespaced_t
@[ end for]@
@(idl_declaration_to_c(member.type, member.name));
@[end for]@
} @(idl_structure_type_to_c_typename(message.structure.namespaced_type));
} @(message_typename);
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Struct for a sequence of @(idl_structure_type_to_c_typename(message.structure.namespaced_type)).
// Struct for a sequence of @(message_typename).
typedef struct @(idl_structure_type_sequence_to_c_typename(message.structure.namespaced_type))
{
@(idl_structure_type_to_c_typename(message.structure.namespaced_type)) * data;
@(message_typename) * data;
/// The number of valid items in data
size_t size;
/// The number of allocated items in data
Expand Down
14 changes: 14 additions & 0 deletions rosidl_generator_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ if(BUILD_TESTING)
rosidl_runtime_c::rosidl_runtime_c
)

add_executable(
test_descriptions_c
test/rosidl_generator_c/test_descriptions.c
)
ament_add_test(
test_descriptions_c
COMMAND "$<TARGET_FILE:test_descriptions_c>"
GENERATE_RESULT_FOR_RETURN_CODE_ZERO
)
target_link_libraries(test_descriptions_c
${c_generator_target}
rosidl_runtime_c::rosidl_runtime_c
)

ament_add_pytest_test(test_hash_generator test/rosidl_generator_type_description
ENV GENERATED_TEST_FILE_DIR=${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_type_description/${PROJECT_NAME}
)
Expand Down
48 changes: 48 additions & 0 deletions rosidl_generator_tests/test/rosidl_generator_c/test_descriptions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2015 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.

#include <stdio.h>
#include <string.h>

#include "rosidl_runtime_c/string.h"
#include "rosidl_runtime_c/type_description/type_source__struct.h"

#include "rosidl_generator_tests/msg/detail/defaults__struct.h"

int main(int argc, char ** argv)
{
(void)argc;
(void)argv;

// Smoke test linkage for extern type description
const rosidl_runtime_c__String * typename =
&rosidl_generator_tests__msg__Defaults__TYPE_DESCRIPTION.type_description.type_name;
// fprintf(stderr, "%s\n", typename->data);
const char * expected_name = "rosidl_generator_tests/msg/Defaults";
if (0 != memcmp(typename->data, expected_name, typename->size)) {
fprintf(stderr, "Defaults typename incorrect.\n");
return 1;
}

// Smoke test linkage for extern type sources
const size_t expected_num_sources = 0; // For now - this will fail when sources get added
const rosidl_runtime_c__type_description__TypeSource__Sequence * sources =
&rosidl_generator_tests__msg__Defaults__RAW_SOURCES;
if (sources->size != expected_num_sources) {
fprintf(stderr, "Defaults didn't have expected number of sources.\n");
return 1;
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
RIHS01_PATTERN = re.compile(r'RIHS([0-9a-f]{2})_([0-9a-f]{64})')

# Used by code generators to create variable names
RAW_SOURCE_VAR = 'RAW_SOURCES'
TYPE_DESCRIPTION_VAR = 'TYPE_DESCRIPTION'
TYPE_HASH_VAR = 'TYPE_HASH'

Expand Down
Loading

0 comments on commit dc3d464

Please sign in to comment.