Skip to content

Commit 143384a

Browse files
committed
Added README to tutorial23.
1 parent cd8ad11 commit 143384a

File tree

3 files changed

+124
-3
lines changed

3 files changed

+124
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ $> nmake install
166166
- [tutorial20](../../tree/master/tutorials/tutorial20) - Reporting protocol version in one of the messages.
167167
- [tutorial21](../../tree/master/tutorials/tutorial21) - Cast between different field types.
168168
- [tutorial22](../../tree/master/tutorials/tutorial22) - Complex length fields.
169+
- [tutorial23](../../tree/master/tutorials/tutorial23) - Reusing definitions from other schemas.
169170

170171

171172
# How-Tos

tutorials/tutorial23/README.md

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,132 @@
11
# Tutorial 23
22
Reusing definitions from other schemas.
33

4+
Sometimes a need may arise to reuse some elements (usually fields) of one schema / protocol in the definition of another.
5+
It can be useful when common complex encoding rules, like [ASN.1](https://en.wikipedia.org/wiki/ASN.1) requiring
6+
custom code injection need to be reused in multiple independent protocols. Version **v5.0** of the
7+
[CommsDSL Specification](https://commschamp.github.io/commsdsl_spec) allow use of multiple independent
8+
schema names when processing multiple schema files and referencing fields of one in another.
9+
10+
Version **v5.0** of the **commsdsl2comms** code generator supports this multi-schema feature, but
11+
requires extra command line parameter `-s` to allow
12+
use of multiple schemas names in the definition of the protocol.
13+
14+
This tutorial uses two schema files:
15+
16+
- [dsl/schema_ext.xml](dsl/schema_ext.xml) which defines external schema with name (and main namespace) "t23_ext".
17+
- [dsl/schema.xml](dsl/schema.xml) which defines schema of this tutorial.
18+
19+
The inter-schema field reference is prefixing the usual field reference with `@ + schema name`.
20+
```xml
21+
<ref field="@t23_ext.ns1.I1" />
22+
```
23+
The generated code (in [include/tutorial23/field/I1.h](include/tutorial23/field/I1.h)) defines
24+
the field (which inherits the name of the referenced field) as an alias type to the field in the `t23_ext` namespace:
25+
```cpp
26+
template <typename TOpt = tutorial23::options::DefaultOptions, typename... TExtraOpts>
27+
using I1 =
28+
t23_ext::ns1::field::I1<
29+
TOpt,
30+
TExtraOpts...
31+
>;
32+
```
33+
The definition of the `t23_ext::ns1::field::I1` field itself is generated in
34+
[include/t23_ext/ns1/field](include/t23_ext/ns1/field) folder, i.e. the [include](include)
35+
folder has two sub-folders for the different namespaces.
36+
37+
The member field of the `Msg` message definition also references field in the external schema.
38+
```xml
39+
<message name="Msg1" id="MsgId.M1" displayName="^Msg1Name">
40+
<ref field="I1" name="F1" />
41+
<ref field="@t23_ext.ns1.S1" name="F2" />
42+
</message>
43+
```
44+
45+
The definition of the `Length` field in the external `t23_ext` schema is taken from the
46+
previous [tutorial22](../tutorial22). Instead of referencing it with the **&lt;ref&gt;**
47+
field definition (which is also possible) the schema just copies its definition using **reuse**
48+
property:
49+
```xml
50+
<bundle reuse="@t23_ext.ns1.Length" reuseCode="true" />
51+
```
52+
Please note the usage of the **reuseCode** property. The **reuse** one just copies the XML definition of the
53+
field without copying any of the custom injected code of the field. Setting **reuseCode** boolean property
54+
ensures that the custom code is also copied. As the result, the `Length` field definition can be
55+
found in the `tutorial23` namespace ([include/tutorial23/field/Length.h](include/tutorial23/field/Length.h)) and
56+
cannot be found in `t23_ext` because it's not really referenced. The `Length` in the `tutorial23` namespace
57+
is referenced by the frame:
58+
```xml
59+
<frame name="Frame">
60+
<sync name="Sync">
61+
<int name="SyncField" type="uint16" defaultValue="0xabdc" />
62+
</sync>
63+
<size name="Size" field="Length" />
64+
<id name="Id" field="MsgId" />
65+
<payload name="Data" />
66+
</frame>
67+
```
68+
69+
Also note that the custom injected code of the `Length` field is located in the folder specifying its
70+
original location ([dsl_src/include/t23_ext/ns1/field](dsl_src/include/t23_ext/ns1/field)).
71+
72+
Using multiple schemas requires extra attention to specifying protocol options
73+
(the classes defined in the [include/tutorial23/options](include/tutorial23/options) folder).
74+
The option classes are designed to be folded and outer classes may extend or override options defined
75+
by the inner ones. Every schema defines its own independent set of options:
76+
77+
- [include/t23_ext/options](include/t23_ext/options) - Options for the elements inside `t23_ext` schema.
78+
- [include/tutorial23/options](include/tutorial23/options) - Options for the elements inside `tutorial23` schema.
79+
80+
In order to combine them the `DefaultOptions` of the protocol (`tutorial23`) schema are expected to wrap and extend
81+
the external (`t23_ext`) one. As the result the [ClientSession](src/ClientSession.h) defines its
82+
options in the following way:
83+
```cpp
84+
using ClientProtocolOptions =
85+
tutorial23::options::ClientDefaultOptionsT<
86+
tutorial23::options::DefaultOptionsT<
87+
t23_ext::options::ClientDefaultOptions
88+
>
89+
>;
90+
```
91+
Without using options from the `t23_ext::options` the compilation will fail because
92+
`t23_ext::ns1::field::S1` [field](include/t23_ext/ns1/field/S1.h) attempts to
93+
access the options referencing `typename TOpt::t23_ext::ns1::field::S1`, which
94+
does not existing in the options provided by the `tutorial23`.
95+
96+
```cpp
97+
template <typename TOpt = t23_ext::options::DefaultOptions, typename... TExtraOpts>
98+
class S1 : public
99+
comms::field::String<
100+
t23_ext::field::FieldBase<>,
101+
TExtraOpts...,
102+
typename TOpt::t23_ext::ns1::field::S1,
103+
comms::option::def::SequenceSerLengthFieldPrefix<typename S1Members<TOpt>::LengthPrefix>
104+
>
105+
```
106+
107+
In addition to the complications around the protocol options definitions, which if not done right may
108+
result in difficult to understand compilation errors, referencing the fields in another schema may
109+
cause problems in different build or packaging systems when multiple independent schemas (protocols) reusing the
110+
common one may attempt to generate and overwrite the same common files.
111+
To cope with this problem the code generation utilities (**commsdsl2comms** and others) allow
112+
renaming different namespaces to avoid clashing.
113+
114+
However, as was shown in this tutorial the fields which are **reuse**-ed rather than
115+
**&lt;ref&gt;**-erenced don't generate code in the external namespace. In case the **all**
116+
the schema fields defined this way, the external namespace will be empty and no code for it
117+
will be generated. As the result the definition of the protocol options are also getting
118+
much simpler.
119+
120+
The bottom line, it is highly recommended to **reuse** the fields from the external schema rather
121+
than **&lt;ref&gt;**-erence them.
4122
5123
## Summary
6124
7-
-
125+
- External schema definitions reuse is supported since **v5.0** of the [CommsDSL](https://commschamp.github.io/commsdsl_spec)
126+
and [commsdsl](https://github/commschamp/commsdsl) code generators.
127+
- Inter-schema referencing is allowed using `@<schema_name>.` prefix.
128+
- When using multiple schemas it is hight recommended to **reuse** the fields rather
129+
than **&lt;ref&gt;**-erence them.
8130
9131
10132
[Read Previous Tutorial](../tutorial22) &lt;-----------------------

tutorials/tutorial23/dsl/schema.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
<ref field="@t23_ext.ns1.I1" />
1515

16-
<ref field="@t23_ext.ns1.S1" />
17-
1816
<bundle reuse="@t23_ext.ns1.Length" reuseCode="true" />
1917
</fields>
2018

0 commit comments

Comments
 (0)