DTDL - Data Type Definition Language

The Data Type Definition Language is used to describe data types used in a schema of foster.

DTDL allows to define classes, lists and structs. Objects inside DataFS contain one or more classes. Lists and structs are used as multi value attributes.

The following sections describe the basic elements of the language.


You can write comments in the files in the C++ format.

    // Comment Type 1

    /* Command Type 2 */


A class has a unique global id and attributes.

If a class does not have a body, then it's called an "external" class. These classes can be used for linking.

    class Type1 [ id({DA249990-6D74-496E-B06A-C0694033665E}) ]
        int32    value1;
        wstring  value2;
        double   value2 [v];   // variable attribute


... same as class, but the struct is packed into a single binary block and stored in one single attribute.


... same as struct. But the items first 16 bytes must be unique. You can use the option 'custom key' if your application can guarantee the uniqueness itself.

    list SampleList [ id({BA506E95-D20C-4E9A-8960-2210E7E46F87}), ck ] // ck for "custom key"
        object  link;		// unique 16 bytes
        wstring strName;

    list SampleList [ id({BA506E95-D20C-4E9A-8960-2210E7E46F88}) ]
        int value;


The language uses to types of preprocessor commands. The #include and #use. They both load an external file. While #include imports the file and all definitions inside completely, the #use command imports all definitions as external definitions.

The difference between the </> and "/" format is how the file is searched. While " takes the current file as starting point, </> takes the input directories passed to the compiler as starting point for the search.

    #include <file.dtdl>
    #include "..\directory\file.dtdl"


Classes, lists and structs can inherit from one or more types. In this case the action of the compiler can be seen as copy-paste of the inherited types into the inheriting type.


DTDL supports namespaces. There are different possibilities to define namespaces. Either using the way known from C++, a shorter way or by simply putting the namespace name in front of the name of a new type.

    namespace a
        namespace b
            class q; // defines a::b::q

    namespace a::b
        class q; // defines a::b::q

    class a::b::q; // defines a::b::q


You can place a description in front of a definition. This description will be stored in the schema and can be seen as documentation.

    [ this is an empty class ]
    class q

Data types

int88 bit signed integer
uint88 bit unsigned integer
int1616 bit signed integer
uint1616 bit unsigned integer
int3232 bit signed integer
uint3232 bit unsigned integer
int6464 bit signed integer
uint6464 bit unsigned integer
int128128 bit signed integer
uint128128 bit unsigned integer
int256256 bit signed integer
uint256256 bit unsigned integer
float32 bit float
double64 bit float
char1 byte character
wchar2 byte character
string1 byte character string
wstringUTF-16 string
bsob[size]binary small object of size 1 to 127 bytes
blob- currently not supported -
stream- currently not supported -
objectobject (an object id or a reference)

Object Types

For values of type 'object' you can specify a set of classes you expect the objects to have when linked by this value. The system does not guarantee that object have all of those classes or restrict operations that cause a violation of these rules.

    objecttype a::b::q.val_obj(type_t); // attribute 'val_obj' of type q in namespace a::b should contain class 'type_t'
© 2020 Mobiland AG