Integrations (PTC products, 3rd party products and code) > Code integration (Ada, ARINC 653, C, C#, C++, IDL, Java, SQL and VB) > C Code > Generating C Code > Overview of generating C code (C code) > Overview of modeling C code (C code) > Overview of modeling C code (C code) > Association and role mapping for C (C code)
  
Association and role mapping for C (C code)
ACS generates Roles applied by Associations and Aggregations as data members (attributes) of a struct. The header file in which the data members are created is determined by the Association Type:
Start-end - generated in the header file created for the Start item.
End-start - generated in the header file created for the End item.
Bi-directional - generated in the header files created for both the Start item and End item.
None - the Association is ignored.
Reverser Notes — When reverse engineering a struct's attributes, the Reverser will reverse engineer an attribute as a Role if all the following statements are true:
The C attribute's data type can be identified as a struct in the code being reverse engineered.
The C struct that is used as a data type is being reverse engineered.
The Reverser cannot match the C attribute to an Attribute in the Model.
If a typed Part has an Association that has not been rolled up to the Part's type, ACS generates a nested struct that is derived from the Part's type. The nested struct defines the Role that is modeled against the Part.
If a Class, Data Type, Interface or Signal owns Parts that are connected through an Association, initialization code is generated in the constructor for the item.
The attribute declaration and initialization is derived from the properties of the Role and the tagged values set for Tag Definitions that are applied to the Roles by the «C Role» stereotype.
Classes Data Types and Interfaces that Implement Interfaces
For Classes, Data Types and Interfaces that implement interfaces:
The first member of the generated struct is named 'base' and is typed by the implementing interface.
ACS generates a 'constructor' function, assigns appropriate functions to the function pointer members of the 'base' member, and assigns values to behavior ports.
The Class, Data Type or Interface provides proxies for functions being forwarded to behavior ports that cast the instance parameter to the correct concrete type before making a call.
For Classes, Data Types or Interfaces containing composite interface-typed non-behavior ports, ACS generates constructor functions that assign functions to the port's function pointer members.
Properties:
Unnamed Roles are generated with an 'r' prefix, and named Roles are generated without an 'r' prefix. Prefixing and suffixing of named and unnamed Roles is controlled through the [role] and [unnamed role] sections of the C_mangle.ini file. For example, if you want all Roles to be generated with an 'r' prefix, ensure that the Role sections of the C_mangle.ini file are as follows:
[role]
AddPrefix=r
AddSuffix=
[unnamed role]
AddPrefix=r
AddSuffix=
For information about how the Behavior property is generated, see the preceding Classes, Data Types and Interfaces that Implement Interfaces section.
If the Composite property is ignored unless the Multiplicity is user defined with a finite value specified, in which case when set to false (Composite check box cleared on Property Pages), a pointer is used.
Example code:
{
struct bar * rRole;
};
If a Default Value is set and the Role has On Class storage, the Role is generated as an attribute initializer in the header or implementation file. If the Role has On Instance storage, the Default Value is ignored.
If the Multiplicity is user defined with a finite value specified, the user defined value is used as the array specifier, unless the C Array Spec tag definition has been set.
Example code:
struct foo
{
struct bar rRole[4];
};
If the Multiplicity is '0 or More' or '1 or More', an array of pointers to the other struct is used, irrespective of whether the Role is Composite or not.
Example code:
struct foo
{
struct bar * rRole;
};
For information about how the Port property is generated, see the preceding Classes, Data Types and Interfaces that Implement Interfaces section.
If the Read Only property is set to TRUE (Read Only check box selected on Property Pages), the const keyword is used.
Example code:
struct foo
{
const bar* m_bar;
};
If the Storage property of a Role is set to On Class, the attribute is generated outside the struct.
Example code:
struct foo
{
struct bar* m_bar;
};
struct bar* theBar; // Storage set to On Class
The Unique property is ignored.
The Visibility property is ignored. A Role is always generated in the struct, which means it will have public visibility.
Example code:
#include "bar.h"
struct foo
{
bar* m_bar;
};
Tag Definitions:
The following tag definitions are applied to a Role by the «C Role» stereotype:
If the tagged value of the C Array Spec tag definition has been set, the value is used as the array, that is, it is generated after the attribute name.
Example code:
struct foo
{
bar* moreBars[3][10];

};
Reverser Notes: When reverse engineering an initializer or array specification that uses a macro, the C Array Spec tag definition is set to the unpreprocessed text.
If the tagged value of the C CV Qualifiertag definition is set to const, volatile or const volatile, the selected keyword is generated before the data type.
Example code:
const foo* m_foo;
volatile foo SomeFoos[10];
const volatile foo EvenMoreFoos[25];
If the tagged value of the C Indirection tag definition has been set, the value is used as an indirection, that is, the value is generated after the data type and before the attribute name.
Example code:
const foo* m_foo;
volatile foo* const m_MoreFoos;
const volatile foo* const * YetMore;
If the tagged value of the C Storage Class tag definition is set (to static, auto, register or extern) and the Role's Storage is On Class, the selected storage class keyword is generated. If the Role's Storage is On Instance, the C Storage Class tag definition is ignored. Note that in the context of a Role, only the static and extern values of the C Storage Class tag definition should be used.
Example code:
struct foo
{
};
struct extern bar m_bar;
struct static bar* m_barPtr;