Compiler problems in generated C++ code

4 posts / 0 new
Last post
Offline
Last seen: 2 years 3 weeks ago
Joined: 01/08/2016
Posts: 3
Compiler problems in generated C++ code

Hello all,

I've run into a number of problems when compiling the C++ code generated from my IDLs in Visual Studio 2013.  I've fixed them manually but I'd like to ask whether it's the "right" fix.  Also consider this a bug report, I suppose :)

Facets of my environment:
1. The code is generated from a hierarchy of IDL files with lots of #includes, inheritance, and composition using included types as fields.
2. I'm using the IDLs of a project in-progress, so I can submit some changes back to them but only if necessary.
3.The code was generated using a script that uses the following command structure on each file in each folder of the heirarchy, outputting the code in a new folder in a mirroring folder hierarchy with a different root dir (it includes the root directory of the source to support relative include paths):
   <path_to_dds> <src_abs_path_to_idl> -I <src_root_dir> -replace -language C++ -d <dest_abs_path>

Problems:
1. One of my IDLs contained an enumerator with the value "FIXED", which the compiler seems to consider a keyword.  I fixed this by prepending it so that the enum value is "v_FIXED" and it works.  Not a major problem, but still a by-hand modification necessary every time the code needs to be regenerated.  First question: To maintain interoperability, do I need to change the "Member name" value in the definition of the corresponding DDS_TypeCode_Member array or anything else?  For example:

static DDS_TypeCode_Member name_of_enum_g_tc_members[1]= { {
   (char *)"FIXED",/* Member name */ /***** change this back to FIXED? *****/ {
     0, /* Ignored */
     DDS_BOOLEAN_FALSE,/* Is a pointer? */
     -1, /* Bitfield bits */
     NULL/* Member type code is assigned later */
   },
   v_FIXED, /* Enumerator ordinal */
   0, /* Ignored */
   0, /* Ignored */
   NULL, /* Ignored */
   RTI_CDR_REQUIRED_MEMBER, /* Is a key? */
   DDS_PRIVATE_MEMBER,/* Member visibility */
   1,
   NULL/* Ignored */ } };


2. It seems that if multiple enumerators contain the same value, the compiler considers it a redefinition (the values aren't scoped within the enumeration).  This caused a problem for several of the IDLs that have the values "OTHER" and "UNKNOWN".  If I can maintain interoperability by renaming it as in my first question, this should be no major problem, but I still need to manually rename the values.

3. In the generated "___Plugin.cxx" files, any #include statements for other "___Plugin.h" files are included in the 'extern "C" {}' scope.  This causes a fatal compiler error C1045 (https://msdn.microsoft.com/en-us/library/aa229004%28v=vs.60%29.aspx) due to nested external linkages.  My solution was to move the #include statements outside of the 'extern "C" {}' scopes as below.  This fixes the compile problem, but I'm concerned that I'm not including something necessary.  Second question: Will I be missing anything by fixing it this way?  I'll find out when I build my application but if this scoping was done for a reason, it would save me some time.


BEFORE:
extern "C" {
   #include "folderA/folderB/InheritedParentPlugin.h"
   #include "folderA/folderC/CompositeFieldPlugin.h"
 ...
 }


AFTER:
#include "folderA/folderB/InheritedParentPlugin.h"
 #include "folderA/folderC/CompositeFieldPlugin.h"
 extern "C" {
 ...
 }


In conclusion, I have manual fixes for these problems but I'm wary of adjusting these generated files and it's going to be repeated work whenever the code needs to be regenerated.

Thanks,
-Eric

Gerardo Pardo's picture
Offline
Last seen: 2 months 2 weeks ago
Joined: 06/02/2010
Posts: 594

Hello Eric,

Thank you for posting this comprehensive explanation of the issue / bug report. It really helps to understand the problem...

I will try to answer each of your points separately.

(1) Collisions between IDL and Language Keywords

By the time they are generated into code the enumeration literals (and member names) have to be chosen to not collide with any programming language Keywords. Which is complicated by the fact that each Programming Language defined a different set of keywords and they evolve over time.

I think rtiddsgen could do a better job detecting this and flagging it at code-generation time rather than letting the compiler give and error... But in any case, I think the problem is best fixed in the IDL file itself (i.g. changing the name of the enum literals or member names).

I think editing the generated code is fraught with potential issues. You could make it work but it is manual work that you would have to keep re-doing and the nature of it can change if a future version of rtiddgen generates different code. There are also issues related to type-compatibility checking and parsing content filter expressions that rely on the field names and having those "manually tweaked"  between the IDL and the generated code is asking for trouble.

Is it not possible for you to modify the IDL?

(2) Collisions on the literals between different enum types.

The standard mapping of IDL to C / C++ specifies that the literal values should be mapped directly into language enums, that is not scoped by the name of the enumeration. One can argue with the wiseness of this decision. I believe the thinking was that the direct mapping allows the person defining the IDL to completely control the enum literal which is something that can be desirable for some applications. If you wanted to scope them you can do it at the time the IDL is defined as in:

enum MyEnum1 {
    MyEnum1_A,
    MyEnum1_B
};  

enum MyEnum2 {
    MyEnum2_A,
    MyEnum2_B
};     

Or alternatively include it into a module:

module Module1 {
    enum MyEnum1 {
        A,
        B
    };
};
module Module2 {
    enum MyEnum {
        A,
        B
    };
};

Again this comes down to being able to modify the IDL. If you cannot do that then the right place to do it would be if rtiddsgen could accept some command-line option to do it for you... But this would need to be implemented.

(3) Included files appearing inside an  extern "C"

This seems a problem.bug in the way rtiddsgen generates the code for included files. I did a bit of digging and I think your solution will work without side-effects. But I would need to look into it deeper to give a more definite answer.

-Gerardo

Offline
Last seen: 2 years 3 weeks ago
Joined: 01/08/2016
Posts: 3

I'll contact the other project about the keyword and conflict issues and see if we can work it out.  The other project primarily uses generated Java code so I'm the first one encountering a lot of the little nuances that come with less type safe languages :)  I guess I was hoping there was a way to separate the message mechanics from the type/field names.

Also appreciate you looking into the extern/include issue.  I'll let you know if I encounter any further problems related to this.  So far, so good.

Thanks again,
-Eric

Offline
Last seen: 2 years 3 weeks ago
Joined: 01/08/2016
Posts: 3

Not sure if this might make an easier fix available, but the conflicting "FIXED" value is defined in the Windows header "wingdi.h".