Replace and Rename Data Types to Conform to Coding Standards

By default, the generated code uses data type aliases such as real_T and int32_T. The code uses these aliases to define global and local variables. If your coding standards require that you use other data type aliases, including aliases that your existing code defines, you can:

  • Configure data type replacement for the entire model.

  • Configure individual data items (such as signals, parameters, and states) to use specific data type aliases.

For information about controlling data types in a model, see Control Signal Data Types.

Inspect External C Code

Save this C code into a file named my_types.h in your current folder. This file represents a header file in your existing code that defines custom data type aliases by using typedef statements.

#include <stdbool.h>

typedef double my_dblPrecision;
typedef short my_int16;
typedef bool my_bool;

Explore Example Model and Default Generated Code

  1. Open the example model ex_data_type_replacement.

    open_system(fullfile(docroot,'toolbox','ecoder','examples',...
    'ex_data_type_replacement'))

  2. On the Modeling tab, click Model Data Editor.

  3. In the Model Data Editor, inspect the Signals tab.

  4. Set the Change view drop-down list to Code. In the data table, the Storage Class column shows that named signal lines such as temp use the storage class ExportedGlobal. With this setting, the signal lines appear in the generated code as separate global variables.

  5. Set the Change view drop-down list to Design.

  6. Update the block diagram.

    Simulink assigns a specific data type to each signal that uses an inherited data type setting such as Inherit: Inherit via internal rule.

  7. In the data table, expand the width of the Data Type column. The column shows that the signals in the model use a mix of the data types int16, double, and boolean. You can also see these data types in the model.

  8. Generate code from the model.

  9. In the code generation report, inspect the shared utility file rtwtypes.h. The code uses typedef statements to rename the primitive C data types by using standard Simulink® Coder™ aliases. For example, the code renames the primitive type double by using the alias real_T.

    typedef double real_T;

  10. Inspect the file ex_data_type_replacement.c. The code uses the default data type aliases to declare and define variables. For example, the code uses the data types real_T, int16_T, and boolean_T to define the global variables flowIn, temp, and intlk.

    real_T flowIn;                         /* '<Root>/In3' */
    int16_T temp;                          /* '<Root>/Add2' */
    boolean_T intlk;                       /* '<S1>/Compare' */

    The model step function defines local variables by using the same data type aliases.

    real_T rtb_Add;
    real_T rtb_FilterCoefficient;

Reuse External Data Type Definitions

Configure the generated code to define variables by using the custom data types defined in my_types.h instead of the default type names.

  1. At the command prompt, create a Simulink.AliasType object for each data type alias that your external code defines.

    Simulink.importExternalCTypes('my_types.h');
    

    In the base workspace, the Simulink.importExternalCTypes function creates the objects my_dblPrecision, my_int16, and my_bool.

    For each object, the function sets the DataScope property to 'Imported' and the HeaderFile property to 'my_types.h'. With these settings, the code generator does not create a typedef statement for each object, but instead the generated code reuses the statements from my_types.h by including (#include) the file.

  2. In the model, in the Configuration Parameters dialog box, on the Code Generation > Data Type Replacement pane, select Replace data type names in the generated code.

  3. Specify the options in the Replacement Name column according to the table.

    Simulink NameReplacement Name
    doublemy_dblPrecision
    int16my_int16
    booleanmy_bool

  4. Generate code from the model.

  5. In the code generation report, inspect the file rtwtypes.h. Now, the code uses an #include directive to import the contents of the external header file my_types.h, which contains the custom data type aliases.

    #include "my_types.h"     /* User defined replacement datatype for int16_T real_T boolean_T  */

  6. Inspect the file ex_data_type_replacement.c. The code uses the custom data type aliases my_dblPrecision, my_int16, and my_bool to define the global variables such as flowIn, temp, and intlk.

    my_dblPrecision flowIn;                /* '<Root>/In3' */
    my_int16 temp;                         /* '<Root>/Add2' */
    my_bool intlk;                         /* '<S1>/Compare' */

    The model step function defines local variables by using the custom data type aliases.

    my_dblPrecision rtb_Add;
    my_dblPrecision rtb_FilterCoefficient;

Create Meaningful Data Type Aliases for Individual Data Items

Suppose that your coding standards require that important data items use a data type whose name indicates the real-world significance. You can create more Simulink.AliasType objects to represent these custom data type aliases. Use the objects to set the data types of data items in the model.

  1. In the Model Data Editor Data Type column, use the Simulink.AliasType objects to set the data types of these block outputs. You can select a signal line in the model, which highlights the corresponding row in the Model Data Editor, or search for the signals in the Model Data Editor by using the Filter contents box.

    BlockOutput Data Type
    Flow Setpointflow_T
    Add2 (which feeds the Compare block)diffTemp_T

  2. Use the Model Data Editor Inports/Outports tab to set the data type of the third Inport block to flow_T.

  3. On the Modeling tab, under Design, click Property Inspector.

  4. Select the block labeled Flow Controller. In the Property Inspector, click Open to open the block dialog box.

  5. On the Data Types tab, set Sum output to ctrl_T. Click OK.

    With these data type settings, some of the named signals, such as temp and flowIn, use data types that evoke real-world quantities, such as liquid flow rate and temperature.

  6. At the command prompt, create Simulink.AliasType objects to represent these new custom data type aliases.

    flow_T = Simulink.AliasType('double');
    diffTemp_T = Simulink.AliasType('int16');
    ctrl_T = Simulink.AliasType('double');

    In the model, the signals flowIn and flowSetPt use the primitive data type double, so the data type alias flow_T maps to double.

  7. Update the block diagram.

    Due to data type inheritance, other signals also use the custom data type aliases. For example, the output data type of the Add block fed by the third Inport block is set to Inherit: Inherit via internal rule. The internal rule chooses the same data type that the block inputs use, flow_T.

  8. Generate code from the model.

  9. The file ex_data_type_replacement_types.h defines the new data types flow_T, diffTemp_T, and ctrl_T as aliases of my_dblPrecision and my_int16.

    typedef my_dblPrecision flow_T;
    typedef my_int16 diffTemp_T;
    typedef my_dblPrecision ctrl_T;

  10. In the file ex_data_type_replacement.c, the code defines global variables by using the new type names.

    flow_T flowIn;                         /* '<Root>/In3' */
    flow_T flowSetPt;                      /* '<Root>/Flow Setpoint' */
    ctrl_T flowCtrl;                       /* '<Root>/Interlock' */
    diffTemp_T temp;                           /* '<Root>/Add2' */
    

  11. For blocks that do not use the new data types, the corresponding generated code continues to use the replacement types that you specified earlier. For example, in the file ex_data_type_replacement.h, the outputs of the blocks In1 and In2 appear as structure fields that use the replacement type my_int16.

    /* External inputs (root inport signals with auto storage) */
    typedef struct {
      my_int16 In1;                        /* '<Root>/In1' */
      my_int16 In2;                        /* '<Root>/In2' */
    } ExtU_ex_data_type_replacement_T;

Create Single Point of Definition for Primitive Types

The custom data type aliases flow_T and ctrl_T map to the primitive data type double. If you want to change this underlying data type from double to single (float), you must remember to modify the BaseType property of both Simulink.AliasType objects.

To more easily make this change, you can create a Simulink.NumericType object and configure both Simulink.AliasType objects to refer to it. Then, you need to modify only the Simulink.NumericType object. A Simulink.NumericType object enables you to share a data type without creating a data type alias.

  1. At the command prompt, create a Simulink.NumericType object to represent the primitive data type single.

    sharedType = Simulink.NumericType;
    sharedType.DataTypeMode = 'Single';

  2. Configure the Simulink.AliasType objects flow_T and ctrl_T to acquire an underlying data type from this new object.

    flow_T.BaseType = 'sharedType';
    ctrl_T.BaseType = 'sharedType';

  3. On the Debug tab, select Information Overlays > Base Data Types Information Overlays > Alias Data Typesand (see Port Data Types). Update the block diagram.

    The data type indicators in the model show that the aliases flow_T and ctrl_T map to the primitive type single. To change this underlying primitive type, you can modify the DataTypeMode property of the Simulink.NumericType object, sharedType.

By default, the Simulink.NumericType object does not cause another typedef statement to appear in the generated code.

If you generate code from the model while the Simulink.NumericType object represents the data type single, the generated code maps flow_T and ctrl_T to the default Simulink Coder data type alias real32_T, which maps to the C data type float. You can replace real32_T in the same way that you replaced real_T, int16_T, and boolean_T (Configuration Parameters > Code Generation > Data Type Replacement).

Permanently Store Data Type Objects

The Simulink.NumericType and Simulink.AliasType objects in the base workspace do not persist if you end your current MATLAB® session. To permanently store these objects, consider migrating your model to a data dictionary. See Migrate Models to Use Simulink Data Dictionary.

Create and Maintain Objects Corresponding to Multiple C typedef Statements

To create Simulink.AliasType objects for a large number of typedef statements in your external C code, consider using the Simulink.importExternalCTypes function.

Related Topics