Skip to content

Commit

Permalink
Generate full type description 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 Apr 3, 2023
1 parent 74cb484 commit 3405deb
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ foreach(dep ${target_dependencies})
endforeach()

get_target_property(_target_sources ${rosidl_generate_interfaces_TARGET} SOURCES)
message(WARNING "TARGET SOURCES ${_target_sources}")

set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c__arguments.json")
rosidl_write_generator_arguments(
"${generator_arguments_file}"
Expand All @@ -91,6 +89,7 @@ rosidl_write_generator_arguments(
TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}"
TARGET_DEPENDENCIES ${target_dependencies}
TYPE_DESCRIPTION_TUPLES "${${rosidl_generate_interfaces_TARGET}__DESCRIPTION_TUPLES}"
ROS_INTERFACE_FILES "${_target_sources}"
)

find_package(Python3 REQUIRED COMPONENTS Interpreter)
Expand Down
79 changes: 73 additions & 6 deletions rosidl_generator_c/resource/full__description.c.em
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ from rosidl_parser.definition import NamespacedType
from rosidl_generator_type_description import FIELD_TYPE_ID_TO_NAME
from rosidl_generator_type_description import GET_DESCRIPTION_FUNC
from rosidl_generator_type_description import GET_HASH_FUNC
from rosidl_generator_type_description import GET_INDIVIDUAL_SOURCE_FUNC
from rosidl_generator_type_description import GET_SOURCES_FUNC

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

def static_seq_n(varname, n):
"""Statically define a runtime Sequence or String type."""
if n > 0:
return f'{{{varname}, {n}, {n}}}'
return '{NULL, 0, 0}'

def static_seq(varname, values):
"""Statically define a runtime Sequence or String type."""
if values:
Expand All @@ -37,6 +44,10 @@ for referenced_td in toplevel_msg['referenced_type_descriptions']:
full_type_descriptions = [toplevel_type_description] + implicit_type_descriptions
full_type_names = [t['type_description']['type_name'] for t, _ in full_type_descriptions]
all_type_descriptions = [toplevel_msg['type_description']] + toplevel_msg['referenced_type_descriptions']

toplevel_encoding = type_source_file.suffix[1:]
with open(type_source_file, 'r') as f:
raw_source_content = f.read()
}@

#include <assert.h>
Expand All @@ -62,6 +73,9 @@ static const rosidl_type_hash_t @(c_typename)__EXPECTED_HASH = @(type_hash_to_c_
static char @(typename_to_c(itype_description['type_name']))__TYPE_NAME[] = "@(itype_description['type_name'])";
@[end for]@

@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Define all values going into each local type
@
@[for msg, interface_type in full_type_descriptions]@
@{
itype_description = msg['type_description']
Expand All @@ -78,7 +92,6 @@ static char @(td_c_typename)__DEFAULT_VALUE__@(field['name'])[] = "@(escape_stri
@[ end if]@
@[ end for]@

/// Define arrays of Fields
@
@[ if itype_description['fields']]@
static rosidl_runtime_c__type_description__Field @(td_c_typename)__FIELDS[] = {
Expand All @@ -97,7 +110,6 @@ static rosidl_runtime_c__type_description__Field @(td_c_typename)__FIELDS[] = {
};
@[ end if]@

/// Define exported TypeDescription and TypeSources
@[ if ref_tds]@
static rosidl_runtime_c__type_description__IndividualTypeDescription @(td_c_typename)__REFERENCED_TYPE_DESCRIPTIONS[] = {
@[ for ref_td in ref_tds]@
Expand Down Expand Up @@ -139,12 +151,67 @@ c_typename = typename_to_c(ref_td['type_name'])
}
return &description;
}
@[end for]@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@# Define Raw Sources
@[if raw_source_content]@
static char toplevel_type_raw_source[] = ""@
@[ for line in raw_source_content.splitlines()]
"@(escape_string(line))\n"@
@[ end for]@
;
@[end if]@
@
static char @(toplevel_encoding)_encoding[] = "@(toplevel_encoding)";
@[if implicit_type_descriptions]@
static char implicit_encoding[] = "implicit";
@[end if]@
@
@[for type_description_msg, interface_type in full_type_descriptions]@
@{
itype_description = type_description_msg['type_description']
td_typename = itype_description['type_name']
td_c_typename = typename_to_c(td_typename)
encoding = 'implicit' if td_typename in implicit_type_names else toplevel_encoding
contents = None if td_typename in implicit_type_names else raw_source_content
}@

const rosidl_runtime_c__type_description__TypeSource *
@(td_c_typename)__@(GET_INDIVIDUAL_SOURCE_FUNC)(
const rosidl_@(interface_type)_type_support_t *)
{
static const rosidl_runtime_c__type_description__TypeSource source = {
@(static_seq(f'{td_c_typename}__TYPE_NAME', td_typename)),
@(static_seq(f'{encoding}_encoding', encoding)),
@(static_seq('toplevel_type_raw_source', contents)),
};
return &source;
}
@[end for]@
@
@[for type_description_msg, interface_type in full_type_descriptions]@
@{
ref_tds = type_description_msg['referenced_type_descriptions']
num_sources = len(ref_tds) + 1
td_c_typename = typename_to_c(type_description_msg['type_description']['type_name'])
}@

const rosidl_runtime_c__type_description__TypeSource__Sequence *
@(td_c_typename)__@(GET_SOURCES_FUNC)(const rosidl_@(interface_type)_type_support_t *)
@(td_c_typename)__@(GET_SOURCES_FUNC)(
const rosidl_@(interface_type)_type_support_t *)
{
@# TODO(ek) Implement raw source code embedding/generation. This sequence is left empty for now.
static const rosidl_runtime_c__type_description__TypeSource__Sequence sources = @(static_seq(None, ''));
return &sources;
static rosidl_runtime_c__type_description__TypeSource sources[@(num_sources)];
static const rosidl_runtime_c__type_description__TypeSource__Sequence source_sequence = @(static_seq_n('sources', num_sources));
static bool constructed = false;
if (!constructed) {
sources[0] = *@(td_c_typename)__@(GET_INDIVIDUAL_SOURCE_FUNC)(NULL),
@[ for idx, ref_td in enumerate(ref_tds)]@
sources[@(idx)] = *@(typename_to_c(ref_td['type_name']))__@(GET_INDIVIDUAL_SOURCE_FUNC)(NULL);
@[ end for]@
constructed = true;
}
return &source_sequence;
}
@[end for]@
3 changes: 2 additions & 1 deletion rosidl_generator_c/resource/idl__description.c.em
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ TEMPLATE(
'full__description.c.em',
toplevel_type_description=toplevel_type_description,
implicit_type_descriptions=implicit_type_descriptions,
hash_lookup=hash_lookup)
hash_lookup=hash_lookup,
type_source_file=type_source_file)
}@
@[end if]@
6 changes: 6 additions & 0 deletions rosidl_generator_c/resource/msg__functions.h.em
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from rosidl_generator_c import idl_structure_type_to_c_typename
from rosidl_generator_c import interface_path_to_string
from rosidl_generator_type_description import GET_DESCRIPTION_FUNC
from rosidl_generator_type_description import GET_HASH_FUNC
from rosidl_generator_type_description import GET_INDIVIDUAL_SOURCE_FUNC
from rosidl_generator_type_description import GET_SOURCES_FUNC

message_typename = idl_structure_type_to_c_typename(message.structure.namespaced_type)
Expand Down Expand Up @@ -101,6 +102,11 @@ const rosidl_runtime_c__type_description__TypeDescription *
@(message_typename)__@(GET_DESCRIPTION_FUNC)(
const rosidl_message_type_support_t *);

ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
const rosidl_runtime_c__type_description__TypeSource *
@(message_typename)__@(GET_INDIVIDUAL_SOURCE_FUNC)(
const rosidl_message_type_support_t *);

/// Retrieve pointer to the raw source texts that defined the description of the message type.
ROSIDL_GENERATOR_C_PUBLIC_@(package_name)
const rosidl_runtime_c__type_description__TypeSource__Sequence *
Expand Down
42 changes: 42 additions & 0 deletions rosidl_generator_tests/test/rosidl_generator_c/test_descriptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ int description_namecheck(

int test_description_linkage();
int test_copied_type_description_struct_hashes();
int test_source_defined();

int main(void)
{
Expand All @@ -68,6 +69,11 @@ int main(void)
fprintf(stderr, "test_copied_type_description_struct_hashes() FAILED\n");
rc++;
}
printf("Testing rosidl_generator_tests embedded raw sources...\n");
if (test_source_defined()) {
fprintf(stderr, "test_source_defined() FAILED\n");
rc++;
}

if (rc != 0) {
fprintf(stderr, "Some tests failed!\n");
Expand Down Expand Up @@ -135,6 +141,42 @@ int test_description_linkage()
return 0;
}

int test_source_defined()
{
// Smoke test that definitions are present for raw type sources
// Message
if (!rosidl_generator_tests__msg__Defaults__get_type_description_sources(NULL)) {
return 1;
}

// Service
if (!rosidl_generator_tests__srv__Empty__get_type_description_sources(NULL)) {
return 1;
}
// Implicit message of a service
if (!rosidl_generator_tests__srv__Empty_Response__get_type_description_sources(NULL)) {
return 1;
}

// Action
if (!rosidl_generator_tests__action__Fibonacci__get_type_description_sources(NULL)) {
return 1;
}
// Implicit message of an action
if (!rosidl_generator_tests__action__Fibonacci_Goal__get_type_description_sources(NULL)) {
return 1;
}
// Implicit service of an action
if (!rosidl_generator_tests__action__Fibonacci_GetResult__get_type_description_sources(NULL)) {
return 1;
}
// Implicit message of implicit service of an action
if (!rosidl_generator_tests__action__Fibonacci_SendGoal_Response__get_type_description_sources(NULL)) {
return 1;
}
return 0;
}

int test_copied_type_description_struct_hashes()
{
#define runtimehash(x) rosidl_runtime_c__type_description__ ## x ## __get_type_hash(NULL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
# Used by code generators to create variable names
GET_DESCRIPTION_FUNC = 'get_type_description'
GET_HASH_FUNC = 'get_type_hash'
GET_INDIVIDUAL_SOURCE_FUNC = 'get_individual_type_description_source'
GET_SOURCES_FUNC = 'get_type_description_sources'


Expand Down
6 changes: 6 additions & 0 deletions rosidl_pycommon/rosidl_pycommon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ def generate_files(
tuple_parts = description_tuple.split(':', 1)
assert len(tuple_parts) == 2
type_description_files[tuple_parts[0]] = tuple_parts[1]
ros_interface_files = {}
for ros_interface_file in args.get('ros_interface_files', []):
p = pathlib.Path(ros_interface_file)
ros_interface_files[p.stem] = p

for idl_tuple in args.get('idl_tuples', []):
idl_parts = idl_tuple.rsplit(':', 1)
Expand All @@ -81,6 +85,7 @@ def generate_files(
type_description_info = json.load(f)

idl_stem = idl_rel_path.stem
type_source_file = ros_interface_files.get(idl_stem, locator.get_absolute_path())
if not keep_case:
idl_stem = convert_camel_case_to_lower_case_underscore(idl_stem)
try:
Expand All @@ -95,6 +100,7 @@ def generate_files(
'interface_path': idl_rel_path,
'content': idl_file.content,
'type_description_info': type_description_info,
'type_source_file': type_source_file,
}
if additional_context is not None:
data.update(additional_context)
Expand Down

0 comments on commit 3405deb

Please sign in to comment.