Reading a union (TCKind.TK_UNION) dynamically

6 posts / 0 new
Last post
Offline
Last seen: 6 years 9 months ago
Joined: 07/12/2012
Posts: 51
Reading a union (TCKind.TK_UNION) dynamically

I am having a problem to read a union from DynamicData. The problem is to read the value of the discriminator so that the member

with the valid data can be identified. I can read all the values of the member fields and of course all but one have invalid data. How does one through

the TypeCode and DynamicData API get the value of the discriminator. The closest I can get to the discriminator is to get only the TypeCode with

discriminator_type(). Can someone point me to the relevant API functions to accomplish this or have a (Java) example to share ?


Thank you

Organization:
Gerardo Pardo's picture
Offline
Last seen: 3 weeks 1 day ago
Joined: 06/02/2010
Posts: 602

 

Hello Nico,

I just checked and the use of the dynamic data API to navigate Union types is not clearly documented, so it is no wonder that you are having problems...

The basic idea is that at any point in time a Union type can hold only a single member.  The member_id for this member is equal to the discriminator value. Therefore to get the value of the discriminator you must the operation  get_member_info_by_index() on the DynamicData using the index value of 0.

The operation get_member_info_by_index () fills in a DynamicDataMemberInfo and accessing the member_id field within that DynamicDataMemberInfo gives you the value of the discriminator you are looking for. 

Once you know the discriminator value you can use the proper-type version if the get_xxx()  operation to access the member value.

Here is an example of the basic calls:

DynamicDataMemberInfo memberInfo = new DynamicDataMemberInfo();
myDynamicData.get_member_info_by_index(memberInfo, 0);
int discriminatorValue = memberInfo.member_id;
int myMemberValue = myDynamicData.get_long(null, discriminatorValue);

I also posted a Java working example on the File Exchange. You can find it at:  http://community.rti.com/filedepot?fid=6 

Gerardo

Offline
Last seen: 6 years 9 months ago
Joined: 07/12/2012
Posts: 51
Hi Gerardo, After struggling with this for a while, I concluded it was the documentation that lacked a description of this. Your explanation and code examples clarified the procedure and I can read unions now. Thank you Nico.
Offline
Last seen: 10 years 10 months ago
Joined: 10/10/2012
Posts: 24

EDIT: Never mind, I've found the soultion now.

Offline
Last seen: 1 year 1 week ago
Joined: 01/01/2017
Posts: 15

Hello,

We have a slight variation of the problem:

We need to use the case values to look up the correct member.

Imagine a variation of the IDL from the snippet:

enum MyUnionMemberType {
        SHORT_MEMBER_DISCRIMINATOR,
        LONG_MEMBER_DISCRIMINATOR,
        FLOAT_MEMBER_DISCRIMINATOR,
        DOUBLE_MEMBER_DISCRIMINATOR,
        STRING_MEMBER_DISCRIMINATOR
};

union MyUnion switch (MyUnionMemberType){
        case SHORT_MEMBER_DISCRIMINATOR:
        case LONG_MEMBER_DISCRIMINATOR:
                long int_member;
        case FLOAT_MEMBER_DISCRIMINATOR:
        case DOUBLE_MEMBER_DISCRIMINATOR:
                double flt_member;
        case STRING_MEMBER_DISCRIMINATOR:
                string<100> string_member;

        default:
                long default_member;
};

The problem is that SHORT_MEMBER_DISCRIMINATOR and LONG_MEMBER_DISCRIMINATOR are both mapped to the member int_member, and similarly FLOAT_MEMBER_DISCRIMINATOR and DOUBLE_MEMBER_DISCRIMINATOR are both mapped to the member flt_member.

Now, we have the union values in a text file with a syntax similar to JSON:

"DOUBLE_MEMBER_DISCRIMINATOR" : "2.345"
"LONG_MEMBER_DISCRIMINATOR" : "765"

and we want to parse this file into DynamicData instances representing the union.

How should we go about this?

Thanks,

Oliver

 

Offline
Last seen: 1 year 1 week ago
Joined: 01/01/2017
Posts: 15

Nevermind, we found a solution.

It involves the function

DDS_UnsignedLong find_member_by_label(DDS_Long label, DDS_ExceptionCode_t &)

Using the traditional C++ API, the steps (omitting the DDS_ExceptionCode_t argument at calls) are:

  1. Given an enum discriminator value as string ( evstr) and given the TypeCode of the discriminant enum type ( etc), loop  ndx from  0 to  etc->member_count() - 1 and compare the  etc->member_name(ndx) with evstr; return  ndx on match.
  2. Set a DDS_Long label = etc->member_ordinal(ndx).
  3. Given the TypeCode of the union ( utc) , set a member index
    DDS_UnsignedLong mIndex = utc->find_member_by_label(label).
  4. Get the corresponding union member TypeCode,
    DDS_TypeCode *branchTc = utc->member_type(mIndex).
  5. Decode the  branchTc TypeCode kind and decide which set function to call
    in the union's corresponding DynamicData object.

- Oliver