forked from OpenDDS/OpenDDS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIDL_COMPILER
725 lines (544 loc) · 25.7 KB
/
IDL_COMPILER
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
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];
---------|---------|---------|---------|---------|---------|---------|---------|
---------|---------|---------|---------|---------|---------|---------|---------|