The document describes how opendds_idl ($DDS_ROOT/dds/idl) generates code to
support DDS sample types defined in IDL.

Naming conventions:
  Functions (& operators) that are overloaded on the IDL types are generated
    in namespace OpenDDS::DCPS and they have the "gen_" (generated) prefix.
  Structs not mentioned in the DDS spec (*_KeyLessThan) are generated in an
  "OpenDDSGenerated" sub-namespace of the user's namespace.

opendds_idl generates code supporting:
a) key comparison
        - gen_has_key(type)
        - struct <type>_KeyLessThan - used for maps of instances
        Keys are identified by zero or more
           #pragma DCPS_DATA_KEY "[<module>::]<type> <key>"
        The key must be a scalar.

b) marshalling
        - marshaling operators (operator<<)
        - demarshaling operators (operator>>)
        - gen_max_marshaled_size(type) method - like marshal or at compile time
        - gen_is_bounded_size(type) method - like marshal or at compile time
        - gen_find_size(type) method -- like max_marshaled_size but use len,
          not max.

c) type-support
        DDS sample types are identified by
        #pragma DCPS_DATA_TYPE "[<module>::]<type>"
        opendds_idl generates IDL and implementation code for sample type
        specific structs:
        <type>TypeSupport IDL & <type>TypeSupportImpl C++
        <type>DataWriter  IDL & <type>DataWriterImpl C++
        <type>DataReader  IDL & <type>DataReaderImpl C++

TAO_IDL is still responsible for:
a) parsing the #pragmas for DCPS_DATA_KEY and DCPS_DATA_TYPE

b) zero-copy read type support ("native" type implementation)
        <type>Seq
        DDS::SampleInfoSeq

        See TAO_IDL/be/be_visitor_native/native_ch.cpp and
        support for #pragmas and generating needed #includes.


===============================================================================
!!!! Below this line are notes leading up to the original implementation !!!!
!!!! They are out-of-date!!!! Use the notes above !!!!!!!!
===============================================================================

---------|---------|---------|---------|---------|---------|---------|---------|
Ideas for DDS compiler.

IDL should is the same except the type name, so a very simple Perl script
could generate the Foo IDL.

Extend the TAO IDL compiler to support DDS
- make the user generate the IDL and then compile so they can put the
  TAO_IDL options they want (like export prefix).
        - step 1) generate IDL
        - step 2) compile IDL

- must generated normal stubs, skelton and CDR streaming for Foo IDL to
        support remote and collocated calls.

- add to servant generation option to fill in servant method implementation
        - method code same for every Foo except a different name.
        - just use the method name to know which code to add.

- in every place that generates CDR streaming code add DDS streaming code
        - put in DDS namespace to avoid conflicts.

- specify the type name with a pragma

- specify the key(s) with a pragma

- what code uses the key(s)
        just lessthan opererator for Foo -> instance map used by
        FooDataWriter and FooDataReader.

-  All IDL will be same except the datatype name.
   The IDL could be generated by sed -e "s/Foo/DataTypeName/g/" Foo.idl

- All Servant method bodies (except marshalling) will also be the same except
  the data type name.

- !!! want extra fast read (zero copy) read method signatures with different
  sequence type (sequence of pointers instead of sequence of values).

---------|---------|---------|---------|---------|---------|---------|---------|
Inputs:
1) IDL defining data type
2) designation of the data type name
3) designation of the key(s)
    designate as field name or fieldname.subfieldname
    no array or sequences
4) ?designation of generated IDL file name.

outputs:
1) IDL for data type: FooTypeSupport, FooDataWriter, FooDataReader
2) zero-copy read/take overload with FooPtrVec (vector of Foo pointers).
     Not in IDL; just via "fast" direct servant calls.
3) servant impls for IDL
4) marshalling code for data type
5) Size of marshalled buffer
6) key support code  (less than operator)


---------|---------|---------|---------|---------|---------|---------|---------|
Idea #1:
1) Have template IDL and Impl that just replaces "Foo" for user data type name.
2) Still need marshaling and key code generated using TAO_IDL
3) still generate sub & skeleton code using TAO_IDL - like any other IDL.

Advantage over #2:
  This impl minimizes the changes to the TAO_IDL compiler.
  TAO_IDL does not have to generate servant code or extra zero-copy read methods
  or any other supporting/non-IDL methods & data members in the servant code.
  Also easier to change servant Impl.

limitation: Foo must be a struct.
            (because the signature is different if Foo is an array typedef
             and also other helping classes are different in FooDefC.h
             example: TAO_Unbounded_Sequence vs TAO_Unbounded_Array_Sequence).

          Is this a limitation required by zero-copy interfaces anyway?
            no but implies added logic in TAO_IDL for idea #2 to handle it.

            We can get around this limitation by making the
            code generation script smarter.

limitation: all generated IDL and servents will be in the global
            module/namespace. Not the module/namespace of the Foo.
            So the Foo name must be unique for a library/executable.

            We can get around this limitation by making the
            code generation script smarter.

Issue: must keep servant template in step with IDL compiler.
       - not a big deal - method signatures will almost never change.


---------|---------|---------|---------|---------|---------|---------|---------|

Usage for idea #1

1) user writes FooDef.idl

// examples contents:

// tell the compiler that "Foo" should have DDS type support
#pragma DCPS_DATA_TYPE "Wyz::Foo "
// tell the compiler that the "id" is one of the keys for Foo
#pragma DCPS_DATA_KEY "Xyz::Foo id"

module Xyz {
struct Possition {
  float x;
  float y;
};

typedef float PossitionArray[2*5];

struct Foo {
  long          id; // the instance key
  LocationArray locs;
  octet         more;
};

};// module Xyz

2) genenerate marshalling support

   # (optional) generate class library export for IDL
   generate_export_file.pl FooLib_Export > foolib_export.h

   tao_idl -Gdcps -Ge 1 -Wb,pre_include=ace\pre.h -Wb,post_include=ace\post.h -I..\..\..\..\..\.. -I..\..\..\..\..\../orbsvcs -GI -Wb,export_macro=FooType_Export -Wb,export_include=footype_export.h FooDef.idl


   # creates FooDef[C,S].[h,inl,cpp] with marshalling helpers
   # in FooDefC.[h,inl,cpp]

   # Do the same for any other any IDL included by FooDef.idl


3) generate the IDL and implemetion from templates
   # Note: this can be done before steps 1 & 2.

   # script just plugs in the given "Foo" type name,
   # and filename of the IDL file defining Foo
   generate_DDS_type_support.pl Foo FooDef.idl

   # generates FooTypeSupport.idl and FooTypeSupportI.h/inl/cpp
       into the current directory.

   # NOTE: all servant code in one FooTypeSupportI.h/inl/cpp
   #      - not in per interface files.

   # Example:
   generate_DDS_type_support.pl -Tstruct Xyz::Foo FooDef.idl \
       -XFooType_export -Mbob::martha

   # where
   #   Xyz:: is the full module path to Foo
   #   Foo is the name of the type to define for DDS/DCPS
   #   FooDef.idl is IDL file containing Foo's definition
   #  -M is module to contain FooTypeSupport, FooDataWriter and FooDataReader
   #       Not the module containing Foo.
   #  -T is Foo's type  (default is 'struct')
   #  -X is the DLL export macro (defaults to none)
   #  -S is sub directory for the IDL file containing Foo
   #       (default is that the fils is in the current directory)




3) generate stubs & skeletons from IDL

   # generate stubs and skeletons - just like normal
   tao_idl -Ge 1 -Wb,pre_include=ace\pre.h -Wb,post_include=ace\post.h -I..\..\..\..\..\.. -I..\..\..\..\..\../orbsvcs -Wb,export_macro=FooType_Export -Wb,export_include=footype_export.h FooTypeSupport.idl


4) User now builds all generated code and uses it.

---------|---------|---------|---------|---------|---------|---------|---------|
limitations of the IDL compiler:
1) data type must be a structure
2) keys must be scalar predefined types and enums (not strings, sequences,
     arrays or structures) but can have multiple keys to support short arrays
     and structures.
3) just one #pragma DCSP_DATA_TYPE per compiler invocation
        must put differnt DCPS data types in different IDL files
---------|---------|---------|---------|---------|---------|---------|---------|
TAO_IDL coding progress chart:

x #pragma DDS_DATA_TYPE
x #pragma DDS_DATA_KEY
- multiple pragmas compiler invocation.

--- struct as base ---
x _tao_has_key()
x FooKeyLessThan()

= serializing/sizing
x/x predefined types (basic scalar types)
x/x array
x/-   array of non-predefined
x/x enum
x/x sequence
x/x   seq of non-predefined
x/x string
x/x struct
x/x union

x/x string in sequence
x/x string in union

---------|---------|---------|---------|---------|---------|---------|---------|
impl idea #2:
- generate IDL by just substituting the DataTypeName
- user creates an IDL file that contains/includes the datatype and the
  generated IDL (?also pragma for DataTypeName and key field(s)).
- run compiler against the user IDL file specifying the DataTypeName and key
  field(s) to generate stubs/servants and marshalling.

# issue: hard to deal with added zero-copy methods and adding servant logic
    Ideas:
      - lookup table for servant logic based on class and type name.
        [] must provide "Foo" name to the compiler.
      - insert impl lookup into be_visitor_operation_is::visit_operation
        in be/be_operation/visitor/operation_is.cpp
      - second pass to make overloaded for zero-copy?
      - must also insert extra helping methods in the servant.


---------|---------|---------|---------|---------|---------|---------|---------|
Usage for idea #2:

1) user writes FooDataType.idl

// examples contents:

// tell the compiler that "Foo" should have DDS type support
// ? is this needed? - why
#pragma DDS_DATA_TYPE "Foo"

// tell the compiler that the "id" is one of the keys for Foo
#pragma DDS_KEY "Foo id"

struct Possition {
  float x;
  float y;
};

typedef float PossitionArray[2*5];

struct Foo {
  long          id; // the instance key
  LocationArray locs;
  octet         more;
};

2) user generates the IDL
   # script just plugs in the given "Foo" type name
   # and include path/name for its IDL file.
   generate_DDS_type_support_idl.pl Foo "subdir/FooDataType.idl"

   # generates FooTypeSupport.idl into the current directory.


3) User compiles the IDL
   # -Gdcps Genables DDS type support for "Foo" type
   # -Gdcps implies -GI - genreate servant but the servant will be complete
   TAO_IDL -Gdcps Foo -Wb,pre_include=ace\pre.h -Wb,post_include=ace\post.h -I..\..\..\..\.. -I..\..\..\..\../orbsvcs FooDataType.idl

#!!! must also compile the FooDataType.idl (and all IDL it includes) with -Gdcps
#So marshalling methods are created for the data types.
   TAO_IDL -Gdcps -Wb,pre_include=ace\pre.h -Wb,post_include=ace\post.h -I..\..\..\..\.. -I..\..\..\..\../orbsvcs FooDataType.idl

   # NOTE: all servant code in one FooTypeI.h/inl/cpp - not in per interface
   #      files.

   # (optional) generate export for IDL
   generate_export_file.pl ExampleFooType > footype_export.h

   # and include other TAO IDL compiler options
   TAO_IDL -Gdcps -Gd -Ge 1 -Wb,pre_include=ace\pre.h -Wb,post_include=ace\post.h -I..\..\..\..\.. -I..\..\..\..\../orbsvcs -Wb,export_macro=ExampleFooType_Export -Wb,export_include=footype_export.h FooType.idl


   # note:  using -Gdcps because DLRL also has generated IDL
   so the general -Gdds does not seem appropirate.


4) User now builds FooTypeI.h/inl/cpp and uses it.
  see TAO\orbsvcs\tests\DDS\DCPS\SimpleFooTest\main.cpp


---------|---------|---------|---------|---------|---------|---------|---------|
Marshalling support notes:

In both idea #1 and #2 the TAO_IDL compiler is modified to generate
DDS marshalling support code.

Each non-scalar type will have:
- marshal operator
- demarshal operator
- _tao_max_marshaled_size(type) method - like marshal or at compile time
- _tao_is_bounded_size(type) method - like marshal or at compile time
- _tao_find_size(type) method -- like max_marshaled_size but use len - not max.

All of these methods would be generated in the same TAO_IDL code that generates
the TAO_Input/OutputCDR streaming operators (if the -Gdcps flag was given).

It is simpler (faster to develop due to the TAO_IDL compiler design)
to generate code to compute max_marshaled_size and is_bounded_size
overloaded operators for every non-scalar type than it is to calculate the
value at compile time for just the Foo type.

note: cache max_marshalled_size and is_fixed_size() in FooDataWriter.

!!! reduce extra visitor code for TAO_IDL by just adding another
be_visitor_root_cdr_op pass with state = TAO_ROOT_!!DDS!!_CDR_OP_CS
(later change to CI) starting in be_visitor_root::visit_root()

 TAO_ROOT_SERIALIZER_OP_CH
 TAO_ROOT_SERIALIZER_OP_CI

Produce same code except TAO_OutputCDR is DDS_OutputCDR (and InputCDR).
Code changes:
  [x] add TAO_ROOT_DDS_CDR_OP_CS enum and use every place TAO_ROOT_CDR_OP_CS is.
  [] fail for unsupported types
  [x] add Serializer includes.
  [] move operators to *C.inl
  [add support in Serializer] arrays
  [] ?remove octet optimizations

--- TAO notes ---
!!! arrays are optimized to call read_<type>_array for primative types
    strm.read_float_array ((ACE_CDR::Float *) _tao_array.out (), 10);
!!! same for sequences
!!! also octet optimization [] !!!! must remove this optimization.

?? operators for types in a scope - how is it different?
  // Set the substate as generating code for the types defined in our scope
  this->ctx_->sub_state (TAO_CodeGen::TAO_CDR_SCOPE);

---------|---------|---------|---------|---------|---------|---------|---------|
About allocator performance

The ACE_Message_Block, ACE_Message_Block and data buffer used to create
buffers for the Serializer writing will have fast allocators when the
Foo data type is fix or a bounded size (when all contained sequences and
strings are bounded).  Allocations for Foo types containing
unbounded types will be slower because they will be off the heap
and will require computing the size of the buffer required for the Foo data
value at run-time (so the Serializer is given a buffer of the correct size).

On the receiving side the Transport contains fast allocators for
ACE_Message_Block, ACE_Message_Block and large read buffers it reads into.

On both the publisher and subscriber sides there will be
fast allocators for the Foo data type.
If the Foo type is fixed size then the fast allocator can
allocate all of the memory.  If the Foo type is bounded or unbounded then
the string and sequence members will allocate off the heap.

Unlike ACE_Dynamic_Allocators when the last chunk/allocation is used
our fast allocators will not fail but will allocate from the heap.
This will support the case when HISTORY.depth and/or
(RESOURCE_LIMITS.max_instances == unlimited or
max_samples_per_instance == unlimited) and
max_samples == unlimited.  In these cases then number of chunks in
the fast allocator is not determined by the DataWriter/Reader's QoS.

?? a Foo containing an array will still be a fixed size and also one
contiguous allocation.
[] verify this.

---------|---------|---------|---------|---------|---------|---------|---------|
How the TAO_IDL compiler BE works:
1) BE_produce visits the tree for specific preproccessing and then visits
   for each file.  The visitor has a be_visitor_context with at state that
   tells the visitor how to specialize its behavior.

2) At various places the context state (or substate) may change and/or
   have extra visits from the same node.

---------|---------|---------|---------|---------|---------|---------|---------|
Change to the TAO_IDL compiler for marshalling & size determination

- change TAO_IDL code that generates CDR operators to also generate
  sizing methods.
An example: be_visitor_structure_cdr_op_cs::visit_structure

- probably better to copy be_visitor_xxx_cdr_op code and modify than
  to make if state == TAO_ROOT_DDS_CDR_OP_CI code paths.

- Create primative type sizing methods
        - in DDS_CDR code

- Must generate includes for DDS_CDR code.

? will typedef float MyFloat;  generate CDR streaming operators?
   ANS: no
        Good - otherwise we might get ambiguous overloads for sizing methods.
                like _tao_max_marshaled_size(MyFloat val);

---------|---------|---------|---------|---------|---------|---------|---------|
Changes to IDL compiler to support servant implementations and zero-copy
    methods; Idea #2 only.

) Change be_visitor_operation_is::visit_operation to lookup predefined code
  based on the method name and the interface name and the Foo name (given
  by -Gdcps parameter.

  Second pass with same method name will be the zero-copy implementation.

) also generate zero-copy methods
  Another pass in be_visitor_operation_is::visit_operation for select methods.
  Must make be_visitor_operation_arglist produce FooPtrVec where it would
  normally produce FooSeq argument.
  Make a global flag to know it is time to produce zero-copy.

  ALTERNATIVE - just have IDL contain method with signarure including
       ShouldBeFooPtrVec and next step would substitue ShouldBeFooPtrVec
       to FooPtrVec.
       Issue: the stub would contain the FooPtrVec but parameter
              handling would be wrong.

) change be_visitor_args_arglist::visit_sequence to
  substitues FooSeq to FooPtrVec.

ALTERNATIVE: could do all of this by post processing of the implementation file.
        Spawn post processing from TAO_IDL compiler. Use Perl.
     1) Find method in Foo[DataTypeSupport|DataWriter|DataReader] and add code.
     2) If zero copy method then copy method interface and substitute FooSeq
        for FooPtrVec.



---------|---------|---------|---------|---------|---------|---------|---------|
key support notes:
=== for map ===
- need less than operator

// like this
struct FooKeyLessThan
{
  bool operator()(const Foo& s1, const Foo& s2) const
  {
    return s1.key1 < s2.key1 && s1.key2 < s2.key2;
  }
};

[] add #pragma DDS_KEY support  (see be_visitor_structure_serializer_op_ch::visit_structure)

- !!! there no less than operators for IDL sequences, arrays and structs.
- limit keys to scalar types.
!!! but what about BuiltInTopicKey_t - it is an array.
[] support array < operator.

!!! need lessthan operator for each user defined type - not just Foo.
  But others can be operator<

less than operators are in stub code.

- generate int TypeSupport::has_key() that returns 1 if the data type has one
  or more keys; otherwise returns 0.
  - maybe has_key() should be in both DataWriter and DataReader.

!!!  has_key() not required but improves efficiency
    Just FooKeyLessThan returns false because there is just one key.
    But can avoid map lookup if has_key() == true so let's do it.

--- how to implment---
save #pragma DDS_DATA_TYPE "Xyz::Foo" in UTL_ScopedName as dcps_data_type_
when TAO_ROOT_SERIALIZER_OP_CH finds dcps_data_type_.equals(node->name) when
generating OpenDDS::DCPS::Serializer stream operators then also generated Foo"KeyLessThan".

-- meaning of "less than" --
What does it mean to be "less than" for an array, sequence or struct?
Must satisfy "Strict Weak Ordering" see http://www.sgi.com/tech/stl/StrictWeakOrdering.html.

Does just comparing all positions satisfy "Strict Weak Ordering"?
struct FooKeyLessThan
{
  bool operator()(const Foo& s1, const Foo& s2) const
  {
    return s1.key1 < s2.key1 && s1.key2 < s2.key2;
  }
};
The above is equivalent to an array of two elements.

ANSWER: yes.


---- compile time checks ---
      // no < or == operator for struct
      //if (foo_write_data == foo_read_data)
         ACE_DEBUG((LM_DEBUG,"test passed\n"));

      // no == or < operators for sequences
      FooSeq fs2;
      FooSeq fs1;
      //if (fs1 < fs2)
      //    ACE_DEBUG((LM_DEBUG,"sequence comparison OK"));

=== for hashmap ===
- need key hash
- need key equality operator

- !!! there no equality operators for IDL sequences, arrays and structs.
- limit keys to scalar types.

- equality is true if all keys are equal.
- hash is sum of hashes

---------|---------|---------|---------|---------|---------|---------|---------|
zero-copy read

See email response on 3/7/05 (? and later) subject = "zero-copy read"

- typedef sequence<Foo> FooSeq does not support zero-copy read because it is
  a sequence of Foo objects (as an array of foo objects) and not Foo pointers.
  ASSUMPTION: the queued Foo may not be in the proper order so the contiguous
    memory of a FooSeq data block is not usable.
    For example: read_instance with PRESENTATION=TOPIC might have the base
        collection with a mix of instances.
    Also it would be hard/impossible to keep a contiguous buffer in order
    because the buffer would need to wrap.
  CONCLUSION: the only way to support zero-copy read is by returning a list
    of pointers to samples.

- IDL does not support a sequence of pointers.

- APPROACH:  overload methods with FooSeq and FooPtrVec parameters.
    typedef std::vector<Foo*> FooPtrVec;

- NOTE: zero-copy read methods will only be available using the
    DataReader object reference;  just when using the "fast"
    DataReader local object -- POA::

- applies to read, take, read_instance, take_instance
   - ?? what about read/take_next_sample/instance ?
        - spec says it is like max_len=0 which would not be zero-copy

Quote from section 2.1.2.5.3.8 read
"PSM mappings that do not provide these facilities may need to change the
signature of the read operation slightly to compensate for it."

IDL sequence has "these facilities" len, max_len, and owns for a sequence
but the sequentialness of the sequence buffer is a problem (as described
above).

Quote from section 2.2.2:
"The DataSample class that associates the SampleInfo and Data collections
 returned from
the data-accessing operations (read and take) have not been explicitly
 mapped into IDL.
The collections themselves have been mapped into sequences. The correspondence
between each Data and SampleInfo is represented by the use of the same index
 to access
the corresponding elements on each of the collections. It is anticipated
 that additional
data-accessing APIs may be provided on each target language to make this
 operation as
natural and efficient is it can be. The reason is that accessing data is the
 main purpose of
the Data-Distribution service, and, the IDL mapping provides a
 programming-language
neutral representation that cannot take advantage of the strengths of
 each particular
language."

NOTE: for IDL PSM the DataSample class is conceptual and the read/take
operations return two parallel sequences.  The PIM also returns two parallel
"arrays".

This quoate from 2.2.2 appears to let us change the read/take methods signatures
to be what ever we want.


---------|---------|---------|---------|---------|---------|---------|---------|
- must copy the value written:

  virtual DDS::ReturnCode_t write (
      const Foo & instance_data,
      DDS::InstanceHandle_t handle
      ACE_ENV_ARG_DECL
    )


- no copy needed of Foo; just copy while marshalling.

---------|---------|---------|---------|---------|---------|---------|---------|
- must copy Foo for register - to map Foo to InstanceHandle_t

  virtual DDS::InstanceHandle_t _cxx_register (
      const Foo & instance_data
      ACE_ENV_ARG_DECL
    )

Is a deep copy supported ?  ANS: yes.
---- compile time checks ---
      FooSeq fs2;
      FooSeq fs1;

      // works
      foo_write_data = foo_read_data;
      // works
      fs2 = fs1;

---- verify the default IDL compiler output support this:

      ACE_DEBUG((LM_DEBUG, "write = %f read = %f\n", foo_write_data.x, foo_read_data.x));
      // yep copies structure conents.
      foo_write_data = foo_read_data;
      ACE_DEBUG((LM_DEBUG, "write = %f read = %f\n", foo_write_data.x, foo_read_data.x));
      // yep just changes x value in read
      foo_read_data.x = 42.5;
      ACE_DEBUG((LM_DEBUG, "write = %f read = %f\n", foo_write_data.x, foo_read_data.x));

DCPS_IR_Domain::add_topic Successfully added topic E61530 id: 1
write = 123.456001 read = -795.294983
write = -795.294983 read = -795.294983
write = -795.294983 read = 42.500000

------
// added a sequence in Foo called floatSeq

//= typedef sequence<float> floatSeq;
//=
//= // Implied IDL for type "Foo"
//= // Example user defined structure
//= struct Foo {
//=   long key;  // the instance key
//=   float x;
//=   float y;
//=   floatSeq fs;
//= };

      Foo f1;
      Foo f2;
      f1.key = 5;
      f2.key = -5;
      floatSeq flseq1;
      flseq1.length(1);
      flseq1[0] = 6;
      floatSeq flseq2;
      flseq2.length(1);
      flseq2[0] = -6;

      f1.fs = flseq1;
      f2.fs = flseq2;

      // yep - a deep copy when a struct has a sequence.
      ACE_DEBUG((LM_DEBUG,"f1.fs[0] = %f f2.fs[0] = %f\n", f1.fs[0], f2.fs[0]));
      f1 = f2;
      ACE_DEBUG((LM_DEBUG,"f1.fs[0] = %f f2.fs[0] = %f\n", f1.fs[0], f2.fs[0]));
      f2.fs[0] = -99;
      ACE_DEBUG((LM_DEBUG,"f1.fs[0] = %f f2.fs[0] = %f\n", f1.fs[0], f2.fs[0]));

      exit(1);


R:\DDS_13a\ACE_wrappers\TAO\orbsvcs\tests\DDS\DCPS\SimpleFooTest>run_test.pl
TAO_DDS_DCPSInfo_i::load_domains Successfully loaded domain E3D420 id: 411
f1.fs[0] = 6.000000 f2.fs[0] = -6.000000
f1.fs[0] = -6.000000 f2.fs[0] = -6.000000
f1.fs[0] = -6.000000 f2.fs[0] = -99.000000
ERROR: SimpleFooTest returned 1



---------|---------|---------|---------|---------|---------|---------|---------|
Finding fixed sizes:
IDL
typedef Location LocationArray[2*5];
generated C++;
typedef Location LocationArray[10];

---------|---------|---------|---------|---------|---------|---------|---------|


---------|---------|---------|---------|---------|---------|---------|---------|
