Introspection

The MARTe2 Introspection and IntrospectionT allow to register in the ClassRegistryDatabase members of a class or a C struct.

This allows to develop components that query and adapt in runtime to the properties of a given class or structure. Examples are the configuration of Objects using structures and the interchange of real-time data between GAMs.

Class/struct register

Note

See the following link for a full data-driven alternative on how to create and register structures.

In order to automatically register a MARTe Object or a C struct into the ClassRegistryDatabase, the following macros must be used:

  • DECLARE_CLASS_MEMBER(className, memberName, type, modifierString, attributeString ), where:
    • className is the name of the class or structure;

    • memberName is the name of the member to be registered;

    • type is the member type (a basic type or a structure);

    • modifierStrubg are the possible member modifiers as described in the documentation of the method GetMemberModifiers of IntrospectionEntry;

    • attributeString is a list of attributes as specified in the documentation of the method GetMemberAtributes of IntrospectionEntry.

  • DECLARE_CLASS_INTROSPECTION(className, introEntryArray) or, in the case of C structs, DECLARE_STRUCT_INTROSPECTION(structName, introEntryArray), where:
    • className is the name of the class and structName is the name of the struct;

    • introEntryArray is a zero terminated array of all the previously declared IntrospectionEntry elements for this class or structure. The entries in the array shall be named &className_memberName_introspectionEntry, where className is the name of the struct of class and memberName is the name of the member to be registered.

struct A {
   MARTe::float32 f1;
   MARTe::float32 f2;
};
struct B {
   struct A a1;
   struct A a2;
};
...
DECLARE_CLASS_MEMBER(A, f1, float32, "", "");
DECLARE_CLASS_MEMBER(A, f2, float32, "", "");
static const MARTe::IntrospectionEntry* AStructEntries[] = { &A_f1_introspectionEntry, &A_f2_introspectionEntry, 0 };
DECLARE_STRUCT_INTROSPECTION(A, AStructEntries)
...
DECLARE_CLASS_MEMBER(B, a1, A, "", "");
DECLARE_CLASS_MEMBER(B, a2, A, "", "");
static const MARTe::IntrospectionEntry* BStructEntries[] = { &B_a1_introspectionEntry, &B_a2_introspectionEntry, 0 };
DECLARE_STRUCT_INTROSPECTION(B, BStructEntries)

Note

This introspection infrastructure is expected to be mostly used by higher level tools, which will automatically generate the required code.

Query instrospection

The introspection information is accessible by querying the ClassRegistryDatabase against the relevant struct/class name and by calling the method GetIntrospection on the retrieved ClassRegistryItem (see example below).

Examples

The following example show how to register a structure, a MARTe object and to how to query their properties in runtime.

Introspection example (ObjectsExample3)
  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
/**
 * @file ObjectsExample3.cpp
 * @brief Source file for class ObjectsExample3
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ObjectsExample3 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ErrorLoggerExample.h"
#include "IntrospectionT.h"
#include "IntrospectionEntry.h"
#include "Object.h"
#include "StreamString.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically registered
 * into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
ControllerEx1    () {
        gain = 0xffu;
    }

    /**
     * A property.
     */
    MARTe::uint32 gain;

    /**
     * Another property.
     */
    MARTe::float32 reference[6];
};

CLASS_REGISTER(ControllerEx1, "")
//Register the member gain
DECLARE_CLASS_MEMBER(ControllerEx1, gain, uint32, "", "");
DECLARE_CLASS_MEMBER(ControllerEx1, reference, float32, "[6]", "");
//The array members must follow the naming convention CLASSNAME_MEMBERNAME_introspectionEntry
static const MARTe::IntrospectionEntry* ControllerEx1ClassEntries[] = { &ControllerEx1_gain_introspectionEntry,
        &ControllerEx1_reference_introspectionEntry, 0 };
//Finally declare the class as introspectable
DECLARE_CLASS_INTROSPECTION(ControllerEx1, ControllerEx1ClassEntries)

//An introspectable structure
struct A {
    MARTe::float32 f1;
    MARTe::float32 f2;
};
struct B {
    struct A a1;
    struct A a2;
};
//The strategy is identical to the class registration
DECLARE_CLASS_MEMBER(A, f1, float32, "", "");
DECLARE_CLASS_MEMBER(A, f2, float32, "", "");
static const MARTe::IntrospectionEntry* AStructEntries[] = { &A_f1_introspectionEntry, &A_f2_introspectionEntry, 0 };
DECLARE_STRUCT_INTROSPECTION(A, AStructEntries)
DECLARE_CLASS_MEMBER(B, a1, A, "", "");
DECLARE_CLASS_MEMBER(B, a2, A, "", "");
static const MARTe::IntrospectionEntry* BStructEntries[] = { &B_a1_introspectionEntry, &B_a2_introspectionEntry, 0 };
DECLARE_STRUCT_INTROSPECTION(B, BStructEntries)

}

static void PrintIntrospection(const MARTe::char8 * const structOrClassToSearch) {
    using namespace MARTe;

    ClassRegistryDatabase *crdSingleton = ClassRegistryDatabase::Instance();
    const ClassRegistryItem *classRegistryItem = crdSingleton->Find(structOrClassToSearch);
    if (classRegistryItem != NULL) {
        //Get the object builder (which knows how to build classes of this type).
        const Introspection *introspection = classRegistryItem->GetIntrospection();
        //Print all the available information.
        if (introspection != NULL) {
            uint32 numberOfMembers = introspection->GetNumberOfMembers();
            uint32 n;
            REPORT_ERROR_STATIC(ErrorManagement::Information, "[%s] number of members: %d:", structOrClassToSearch, numberOfMembers);
            for (n = 0u; n < numberOfMembers; n++) {
                const IntrospectionEntry entry = introspection->operator [](n);
                const char8 * const memberName = entry.GetMemberName();
                const char8 * const memberType = entry.GetMemberTypeName();
                const char8 * const memberModifiers = entry.GetMemberModifiers();
                const char8 * const memberAttributes = entry.GetMemberAttributes();
                REPORT_ERROR_STATIC(ErrorManagement::Information, "[%d] [name]: %s [type]: %s [mods]: %s [attrs]: %s", n, memberName, memberType, memberModifiers, memberAttributes);
            }
        }
        else {
            REPORT_ERROR_STATIC(ErrorManagement::FatalError, "No introspection available for struct or class "
                    "with name: %s", structOrClassToSearch);
        }
    }
    else {
        REPORT_ERROR_STATIC(ErrorManagement::FatalError, "Could not find struct or class "
                "with name: %s", structOrClassToSearch);
    }
}

int main(int argc, char **argv) {
    using namespace MARTe;
    using namespace MARTe2Tutorial;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    PrintIntrospection("ControllerEx1");
    PrintIntrospection("A");
    PrintIntrospection("B");

    return 0;
}

Instructions on how to compile and execute the examples can be found here.