From 061dc8f513e1cb264ef9c66c40eccc2f97de0ba9 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Wed, 12 Mar 2014 10:44:40 +0400 Subject: [PATCH] Fixed linking of generated types - generated types are templates now, which allows to define static constant member in headers avoiding linking errors --- .../dsdl_compiler/data_type_template.tmpl | 54 ++++++++----------- libuavcan/dsdl_compiler/dsdlc.py | 2 +- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/libuavcan/dsdl_compiler/data_type_template.tmpl b/libuavcan/dsdl_compiler/data_type_template.tmpl index 63a7519e77..fb75a4855c 100644 --- a/libuavcan/dsdl_compiler/data_type_template.tmpl +++ b/libuavcan/dsdl_compiler/data_type_template.tmpl @@ -8,21 +8,6 @@ #pragma once -/* - * Forward declaration - */ -% for nsc in t.cpp_namespace_components: -namespace ${nsc} -{ -% endfor - -struct ${t.cpp_type_name}; -typedef ${t.cpp_type_name} ${t.short_name}; - -% for nsc in t.cpp_namespace_components: -} -% endfor - #include #include @@ -55,11 +40,12 @@ namespace ${nsc} UAVCAN_PACKED_BEGIN #endif +template struct ${t.cpp_type_name} { -<%def name="generate_primary_body(type_name, max_bitlen, fields, constants)" buffered="True"> - typedef const ${type_name}& ParameterType; - typedef ${type_name}& ReferenceType; +<%def name="generate_primary_body(typedef_name, ctor_name, max_bitlen, fields, constants)" buffered="True"> + typedef const ${typedef_name}& ParameterType; + typedef ${typedef_name}& ReferenceType; <%def name="expand_attr_types(group_name, attrs)"> struct ${group_name} @@ -92,22 +78,24 @@ struct ${t.cpp_type_name} % if a.cpp_use_enum: enum { ${a.name} = ${a.cpp_value} }; // ${a.init_expression} % else: - static const typename ::uavcan::StorageType< ConstantTypes::${a.name} >::Type ${a.name}; // ${a.init_expression} + static const typename ::uavcan::StorageType< typename ConstantTypes::${a.name} >::Type ${a.name}; // ${a.init_expression} %endif % endfor // Fields % for a in fields: - typename ::uavcan::StorageType< FieldTypes::${a.name} >::Type ${a.name}; + typename ::uavcan::StorageType< typename FieldTypes::${a.name} >::Type ${a.name}; % endfor - ${type_name}() + ${ctor_name}() % for idx,a in enumerate(fields): ${':' if idx == 0 else ','} ${a.name}() % endfor { enum { MaxByteLen = ::uavcan::BitLenToByteLen::Result }; ::uavcan::StaticAssert::check(); + + ::uavcan::StaticAssert::check(); // Usage check #if UAVCAN_DEBUG /* * Cross-checking MaxBitLen provided by the DSDL compiler. @@ -118,8 +106,8 @@ struct ${t.cpp_type_name} #endif } - bool operator!=(const ${type_name}& rhs) const { return !operator==(rhs); } - bool operator==(const ${type_name}& rhs) const + bool operator!=(ParameterType rhs) const { return !operator==(rhs); } + bool operator==(ParameterType rhs) const { % if fields: return @@ -151,15 +139,15 @@ ${'::uavcan::TailArrayOptDisabled' if (idx + 1) < len(fields) else 'tao_mode'}); % if t.kind == t.KIND_SERVICE: struct Request { - ${generate_primary_body('Request', t.get_max_bitlen_request(), t.request_fields, t.request_constants) | indent} + ${generate_primary_body('Request', 'Request', t.get_max_bitlen_request(), t.request_fields, t.request_constants) | indent} }; struct Response { - ${generate_primary_body('Response', t.get_max_bitlen_response(), t.response_fields, t.response_constants) | indent} + ${generate_primary_body('Response', 'Response', t.get_max_bitlen_response(), t.response_fields, t.response_constants) | indent} }; % else: - ${generate_primary_body(t.cpp_type_name, t.get_max_bitlen(), t.fields, t.constants)} + ${generate_primary_body(t.cpp_type_name + '', t.cpp_type_name, t.get_max_bitlen(), t.fields, t.constants)} % endif /* @@ -208,27 +196,31 @@ private: <%def name="define_out_of_line_constants(scope_prefix, constants)"> % for a in constants: % if not a.cpp_use_enum: -const typename ::uavcan::StorageType< ${scope_prefix}::ConstantTypes::${a.name} >::Type +template +const typename ::uavcan::StorageType< typename ${scope_prefix}::ConstantTypes::${a.name} >::Type ${scope_prefix}::${a.name} = ${a.cpp_value}; // ${a.init_expression} + %endif % endfor % if t.kind == t.KIND_SERVICE: -${define_out_of_line_constants(t.cpp_type_name + '::Request', t.request_constants)} -${define_out_of_line_constants(t.cpp_type_name + '::Response', t.response_constants)} +${define_out_of_line_constants(t.cpp_type_name + '::Request', t.request_constants)} +${define_out_of_line_constants(t.cpp_type_name + '::Response', t.response_constants)} % else: -${define_out_of_line_constants(t.cpp_type_name, t.constants)} +${define_out_of_line_constants(t.cpp_type_name + '', t.constants)} % endif #if UAVCAN_PACK_STRUCTS UAVCAN_PACKED_END #endif +typedef ${t.cpp_type_name}<0> ${t.short_name}; + % if t.has_default_dtid: namespace { -const ::uavcan::DefaultDataTypeRegistrator< ${t.cpp_type_name} > _uavcan_gdtr_registrator_${t.cpp_type_name}; +const ::uavcan::DefaultDataTypeRegistrator< ${t.cpp_full_type_name} > _uavcan_gdtr_registrator_${t.short_name}; } % else: diff --git a/libuavcan/dsdl_compiler/dsdlc.py b/libuavcan/dsdl_compiler/dsdlc.py index bf64fb53c7..17d8bd1a3a 100755 --- a/libuavcan/dsdl_compiler/dsdlc.py +++ b/libuavcan/dsdl_compiler/dsdlc.py @@ -161,7 +161,7 @@ def generate_one_type(t): c.cpp_value = c.string_value else: int(c.string_value) # Making sure that this is a valid integer literal - c.cpp_use_enum = c.value >= 0 and c.value.bit_length() <= MAX_BITLEN_FOR_ENUM + c.cpp_use_enum = c.value >= 0 and c.type.bitlen <= MAX_BITLEN_FOR_ENUM c.cpp_value = c.string_value if c.type.kind == c.type.KIND_UNSIGNED_INT: c.cpp_value += 'U'