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.
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;
Open the example model ex_data_type_replacement.
open_system(fullfile(docroot,'toolbox','ecoder','examples',... 'ex_data_type_replacement'))
On the Modeling tab, click Model Data Editor.
In the Model Data Editor, inspect the Signals tab.
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.
Set the Change view drop-down list to
Design
.
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
.
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.
Generate code from the model.
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;
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;
Configure the generated code to define variables by using the custom data types
defined in my_types.h
instead of the default type names.
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.
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.
Specify the options in the Replacement Name column according to the table.
Simulink Name | Replacement Name |
---|---|
double | my_dblPrecision |
int16 | my_int16 |
boolean | my_bool |
Generate code from the model.
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 */
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;
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.
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.
Block | Output Data Type |
---|---|
Flow Setpoint | flow_T |
Add2 (which feeds the Compare block) | diffTemp_T |
Use the Model Data Editor Inports/Outports tab to
set the data type of the third Inport block to
flow_T
.
On the Modeling tab, under Design, click Property Inspector.
Select the block labeled Flow Controller. In the Property Inspector, click Open to open the block dialog box.
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.
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
.
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
.
Generate code from the model.
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;
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' */
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;
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.
At the command prompt, create a Simulink.NumericType
object to represent the primitive
data type single
.
sharedType = Simulink.NumericType;
sharedType.DataTypeMode = 'Single';
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';
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).
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.
typedef
StatementsTo create Simulink.AliasType
objects for a large
number of typedef
statements in your external C code, consider
using the Simulink.importExternalCTypes
function.