Classes
Embedded Engineer can emit plain C-code which you can use with any toolchain that supports C89 or higher. This has many benefits, one being a small footprint of the resulting executable, another the availability of C-compilers for nearly every platform imaginable.
However, this comes with a trade-off: While C was not built with object orientation support in mind, object orientation is a fundamental concept in UML2.
Therefore, the code generator has to translate the object oriented model into C-code which does not support many of the object oriented concepts natively.
The following chapters explain how the code generator performs this translation for the elements typically found in a class, and how this transformation can be adjusted.
The Class
The class itself is translated to a struct which contains every attribute in the class, and also instance variables for the state machines of the class.
- The current instance is always available through the variable
me
. - Attributes in UML classes correspond to fields in C-structures.
- Static attributes are not part of any structure.
- Access control modifiers do not get translated in general, except with private static attributes, which will be generated as static variables.
- External variables are specified by the extern stereotype on attributes.
Instantiation
Embedded Engineer, when using AnsiC, will generate for each Class a Class struct containing all private Attributes and the StateMachine structs to pose as a type for instantiation.
This Class and StateMachine struct can be used to generate multiple instances. Either by creating a variable/pointer to the struct or by modelling it.
Attributes
Attributes are a vital part of every class in UML2. For the most part, the translation to C-code is straightforward. For example, type respectively name will be equivalent in the generated code and the model.
However, there are a few specialities to enable features of C which are not part of UML2:
- If you specify the stereotype
extern
, the attribute will beextern
(also available in the Toolbox). - Static
static
attributes will be generated as top level variables.private
static
attributes will be hidden from other compilation unitspublic
static
attributes will be available by including the .h file of the class.
private
/public
affects only top level attributes (for example attributes of static classes).- For non-static attributes, the attribute will be set to the initial value when calling the constructor-method.
- For
static
attributes, the attribute will be declared and defined at once. - readonly attributes can be created with the
readonly
stereotype.
Operations
Operations in UML2 are usually part of classes, as such the code generation works as follows.
For methods, a parameter is inserted which should point to an instance of the generated C structure. The default name of this parameter is me
(in C++, the object orientation support of the language is used, so this reference is called this
). For method calls in activity or state machine diagrams, this parameter is automatically assigned to me
. For details how the name of an operation is generated, see the Operations chapter.
For static operations (functions), there is no such automatic parameter introduction. For Singletons, the situation is similar.
Singleton
The code generator supports the singleton pattern. If you mark a class with the stereotype singleton
(for example by using the Toolbox), the generated operations and behaviors of that class will access a statically allocated structure, and therefore have no explicit parameter for the class.
You can still access the class in your operations and behaviors with me – the necessary code is automatically added to the generated functions – but you never have to pass the parameter around explicitely.
Warning
Please use the singleton pattern wisely, it's probably the pattern which is misused the most, and it's hard to use it correctly. While it makes modeling easier because you don't have to care about the instance variable, only use it if you really have to.
Static Classes
With Embedded Engineer you have the possibility to mark classes as static. Just give them the stereotype static
(for example by using the Toolbox).
This has the following effects:
- No structure will be generated for the class, therefore you cannot have behavioral models which depend on a structure in a static class. Effectively this means that you can have activities in a static class, but no state machines.
- Private attributes will be generated as static variables in the .c file of the class, effectively hiding them from other modules.
- Public attributes will be generated as variables in the .c file of the class, with the corresponding extern declaration in the public .h file.
- If an initial value is defined for an attribute, the corresponding variable in C will be set to this value.
- All operations of this class will be static automatically. You don't have to mark them as static explicitely.
Skip Code Generation
You can skip code generation for a class and all its members by specifying the NoCodeGen
tagged value or the no code generation
Stereotype, and set the value to true
.
The NoCodeGen
tagged value can be set on packages or class elements.
- If set on a class the generation for this class and its behavior will be skipped.
- If set on a package the package and all contained elements and packages will be skipped
Entry Point
If you want to define an Entry Point to your application, for example if you want to generate all of your code, you can define a class as entry point for the application.
To do so, give the class the stereotype executable entry point
. You can do this by using the Toolbox, or you can add it manually.
Now you have to define which behavior you'd like as entry to the application. You can do so by adding the tagged value ClassifierBehavior
(if you have the MDG technology for LieberLieber Embedded Engineer enabled, this will automatically be done for you when you apply the stereotype), and selecting the operation/functionbehavior as value for the tag:
Now this method or behavior will be treated specially. Its name will never be changed, so you can rely on this name, for example for defining a main function.
Classifier Behaviors
Please see the chapter Entry Point to find out more about classifier behaviors.
Custom Naming
Since it is sometimes necessary or wanted to have a "full qualified name" in the model, but only an acronym or other pre/suffixes in the class and/or file names as well as custom extensions, we extended the Embedded Engineer Profile to support such a feature.
This Stereotype/these Tagged Values can be applied to any class and/or package and will be "inherited" (until overwritten) by all sub/child elements.
Since version 3.2 also Enumerations can use the CustomSettings
Stereotype/Tagged Values.
The new Stereotype CustomSettings
was created to contain the new Custom naming Tagged Values:
CustomClassName
Name | CustomClassName |
---|---|
Description | Allows the user to define a custom class name differing from the model element name. |
Format1 | Any string and Placeholders combination. |
Example | {ClassName}_tst Class name with custom suffix separated by _ |
CustomExtension
Name | CustomExtension |
---|---|
Description | Allows the user to define a custom file extension for implementation and/or declaration. Either implementtion or implementation and declaration, delimited by ; . |
Format1 | .imp;[.decl] |
Example | .cxx;.hxx File extensions change to .cxx and .hxx |
CustomFileName
Name | CustomFileName |
---|---|
Description | Allows the user to define a custom file name differing from the model element name. |
Format1 | Any string and Placeholders combination. |
Example | {Owner}_{ClassName} File name with owner name as prefix separated by _ |
Placeholders
To allow the reuse of the definition for multiple classes (e.i. on package level) CustomClassName
and CustomFileName
support placeholders witch will be replaced with model relevant information
Placehoder | Replacement value |
---|---|
{ClassName} |
Will be replaced with the name of the currently generated class element. |
{Owner} |
Will be replaced with the name of the owner/parent element of the currently generated class element. |
See also