Main Content

Simulink.importExternalCTypes

Generate Simulink representations of custom data types defined by C or C++ code

Description

importInfo = Simulink.importExternalCTypes(headerFiles) parses the C or C++ header files (.h or .hpp) identified by headerFiles for typedef, struct, and enum type definitions, and generates Simulink® representations of the types. The output, importInfo, identifies the successfully and unsuccessfully imported types.

You can use the Simulink representations to:

By default, the function:

  • Imports an enumerated type by generating a script file that derives an enumeration class from Simulink.IntEnumType, as described in Define Simulink Enumerations. If necessary, you can then edit the class definition to customize it (for example, by implementing the addClassNameToEnumNames method).

  • Imports a structure type by generating a Simulink.Bus object in the base workspace.

  • Imports a primitive typedef statement by generating a Simulink.AliasType object in the base workspace.

  • Interprets generic C data types, such as int or short, according to the word lengths of your host computer. For example, for most modern machines, int has a 32-bit word length, so the function represents an int structure field as a bus element that uses the Simulink data type int32.

    To override this default behavior, identify your target hardware board by using the HardwareImplementation pair argument.

For additional information about default behavior, see Tips.

example

importInfo = Simulink.importExternalCTypes(modelName) generates Simulink representations of custom C data types by analyzing a model that you identify with modelName. When you use the Simulation Target configuration parameters in a model to identify header files for inclusion during simulation, use this syntax to import types for the purpose of simulating the model on your host computer. The function interprets generic C data types according to the word lengths of your host computer.

When you use this syntax, do not use pair arguments, such as HardwareImplementation, that can conflict with the configuration parameters of the target model. When you use such pair arguments with this syntax, the function generates a warning.

example

importInfo = Simulink.importExternalCTypes(___,Name,Value) specifies additional options using one or more name-value pair arguments. You can use this syntax to:

  • Specify the names of types to import by using the Names pair argument.

  • Control the way that Simulink stores the imported types, for example, by generating the types in a Simulink data dictionary. Use the MATFile and DataDictionary pair arguments.

  • Control the way that the function interprets generic C data types. Use the HardwareImplementation pair argument.

  • Maintain synchrony between the C-code definitions and the Simulink representations by attempting to import the updated C-code definitions again. You can choose whether to overwrite the existing Simulink representations. Use the Overwrite and Verbose pair arguments.

example

Examples

collapse all

This example shows how to generate Simulink representations of a C structure type (struct) and an enumerated (enum) data type from a header file.

In your current folder, create the file ex_cc_simpleTypes.h.

typedef enum {
  PWR_LOSS = 0,                 /* Default value */
  OVERSPD,
  PRESS_LOW,
} fault_T;

typedef struct {
    double coeff;
    double init;
} params_T;

Generate Simulink representations of the types by calling Simulink.importExternalCTypes.

Simulink.importExternalCTypes('ex_cc_simpleTypes.h');

The function creates a Simulink.Bus object, params_T, in the base workspace.

To inspect the properties of the object, open the Type Editor.

typeeditor

Each bus element uses a name and a data type (double) that match the corresponding structure field in ex_cc_simpleTypes.h.

In your current folder, inspect the generated file, fault_T.m, which defines the enumerated type fault_T as an enumeration class.

You can use the bus object and the enumeration class to set signal and parameter data types in Simulink models.

This example shows how to generate a Simulink representation of a structure type whose fields use custom data types (typedef).

Create the file ex_integer_aliases.h in your current folder.

typedef int sint_32;

typedef unsigned short uint_16;

Create the file ex_cc_struct_alias.h in your current folder.

#include "ex_integer_aliases.h"

typedef struct {
    sint_32 accum;
    uint_16 index;
} my_ints_T;

Import the structure type into Simulink as a Simulink.Bus object in the base workspace. Import the typedef statements as Simulink.AliasType objects.

Simulink.importExternalCTypes('ex_cc_struct_alias.h');

Inspect the data types of the bus elements in the bus object. For example, inspect the DataType property of the first bus element, which corresponds to the structure field accum.

my_ints_T.Elements(1)
ans = 

  BusElement with properties:

              Name: 'accum'
        Complexity: 'real'
        Dimensions: 1
          DataType: 'sint_32'
               Min: []
               Max: []
    DimensionsMode: 'Fixed'
        SampleTime: -1
              Unit: ''
       Description: ''

The Simulink.importExternalCTypes function uses the generated Simulink.AliasType objects to set the data types of the bus elements.

Inspect the Simulink.AliasType objects in the base workspace. For example, the object named sint_32 corresponds to one of the typedef statements in ex_integer_aliases.h.

sint_32
sint_32 = 

  AliasType with properties:

    Description: ''
      DataScope: 'Imported'
     HeaderFile: 'ex_integer_aliases.h'
       BaseType: 'int32'

For most host computers (which the function targets by default), the word length of int is 32 bits and the word length of unsigned short is 16 bits. The function maps int and unsigned short to the Simulink types int32 and uint16.

If you have Embedded Coder, the code that you generate from the model can use sint_32 and uint_16 instead of the standard data type names, int32_T and uint16_T.

This example shows how to store the imported data types in a Simulink data dictionary. A data dictionary stores data specifications (such as for signals and block parameter values), data types, and other design data for one or more Simulink models.

In your current folder, create the file ex_cc_simpleTypes.h.

typedef enum {
  PWR_LOSS = 0,            /* Default value */
  OVERSPD,
  PRESS_LOW,
} fault_T;

typedef struct {
    double coeff;
    double init;
} params_T;

Create a subfolder called myDictionaries.

mkdir('myDictionaries')

Generate Simulink representations of the types by calling Simulink.importExternalCTypes. Permanently store the type definitions by creating a new data dictionary, ex_cc_myTypes.sldd, in the new subfolder.

Simulink.importExternalCTypes('ex_cc_simpleTypes.h',...
    'DataDictionary','ex_cc_myTypes.sldd',...
    'OutputDir','myDictionaries');

To inspect the contents of the dictionary, set your current folder to myDictionaries and double-click the dictionary file.

To use the Simulink representations in the dictionary, you must link a model or models to the dictionary. See Migrate Models to Use Simulink Data Dictionary.

This example shows how to generate Simulink representations only for enumerated and structure data types that you identify by name.

In your current folder, create the file ex_cc_manySimpleTypes.h. The file defines three structure types: params_T, signals_T, and states_T.

typedef struct {
    double coeff;
    double init;
} params_T;

typedef struct {
    double flow_rate;
    double steam_press;
} signals_T;

typedef struct {
    double accum;
    double error;
} states_T;

Generate Simulink representations only for params_T and signals_T.

Simulink.importExternalCTypes('ex_cc_manySimpleTypes.h',...
    'Names',{'params_T','signals_T'});

The Simulink.Bus objects, params_T and signals_T, appear in the base workspace.

By default, Simulink.importExternalCTypes represents an enumerated data type by creating an enumeration class that derives from the built-in class Simulink.IntEnumType. When you simulate or generate code from a model that uses the generated class, configuration parameters that you select for the model (for example, on the Hardware Implementation pane) determine the specific integer length that Simulink.IntEnumType and the enumeration class employ.

By default, the function interprets generic, primitive C data types, such as short and int, according to the word lengths of your host computer. For example, to represent an int structure field, the function typically applies the 32-bit data type int32 to the corresponding bus element. When you want to simulate and generate code for hardware other than your host computer, use the HardwareImplementation pair argument to identify the target hardware and, by extension, the word lengths of the hardware.

This example shows how to import data types from code that you intend to use on 16-bit hardware. For this board, int has a 16-bit length, and each item of enumerated data (enum) consumes 16 bits.

In your current folder, create the file ex_cc_intTypes.h.

typedef enum {
  PWR_LOSS = 0,            /* Default value */
  OVERSPD,
  PRESS_LOW,
} fault_T;

typedef struct {
    int coeff;
    int init;
} params_T;

The code defines an enumerated data type and a structure type whose fields use the generic C data type int.

To generate an accurate Simulink representation of the structure type, first open an existing model or create a new model. For this example, create a new model named ex_hdwImpl_16bit.

In the new model, set Configuration Parameters > Hardware Implementation > Device vendor to Atmel. Set Device type to AVR.

Alternatively, at the command prompt, use these commands to create and configure the model:

new_system('ex_hdwImpl_16bit','Model');
set_param('ex_hdwImpl_16bit','ProdHWDeviceType','Atmel->AVR')

Generate Simulink representations of the types. To specify the word lengths of the target 16-bit hardware, extract the model configuration parameters (which include the Hardware Implementation settings) as a Simulink.ConfigSet object.

configSet = getActiveConfigSet('ex_hdwImpl_16bit');
Simulink.importExternalCTypes('ex_cc_intTypes.h','HardwareImplementation',configSet);

The Simulink.Bus object params_T appears in the base workspace. The bus elements, such as coeff, use the Simulink data type int16.

params_T.Elements(1)
ans = 

  BusElement with properties:

              Name: 'coeff'
        Complexity: 'real'
        Dimensions: 1
          DataType: 'int16'
               Min: []
               Max: []
    DimensionsMode: 'Fixed'
              Unit: ''
       Description: ''

In your current folder, the file fault_T.m defines the enumeration class fault_T. The class derives from Simulink.IntEnumType, so you must use model configuration parameters to identify the target hardware and, by extension, the correct native integer length.

Create the file ex_cc_fixpt_struct.h in your current folder.

typedef struct {
    
    int coeff;   /* Word length 16, 
       binary fraction length 7 */
    
    int init;   /* Word length 16, 
       binary fraction length 3 */
    
} params_T;

The file defines a structure type whose fields use fixed-point data types. For example, the structure stores the field coeff in a signed, 16-bit integer data type. A binary fraction length of 7 relates the stored integer value to the real-world value.

Suppose that this code operates on 16-bit hardware (such that the generic C data type int has a 16-bit word length). To generate a Simulink representation of the type, first create a coder.HardwareImplementation object that identifies the hardware.

hdw = coder.HardwareImplementation;
hdw.ProdHWDeviceType = 'Atmel->AVR';

Generate a Simulink representation of the structure type.

Simulink.importExternalCTypes('ex_cc_fixpt_struct.h',...
    'HardwareImplementation',hdw);

The Simulink.Bus object, params_T, appears in the base workspace. Each bus element, such as coeff, uses the data type int16.

params_T.Elements(1)
ans = 

  BusElement with properties:

              Name: 'coeff'
        Complexity: 'real'
        Dimensions: 1
          DataType: 'int16'
               Min: []
               Max: []
    DimensionsMode: 'Fixed'
              Unit: ''
       Description: ''

Simulink.importExternalCTypes cannot infer the fixed-point scaling (binary fraction length) from the C code. You must manually specify the data types of the bus elements. To specify the data types at the command prompt, use the fixdt function.

params_T.Elements(1).DataType = 'fixdt(1,16,7)';
params_T.Elements(2).DataType = 'fixdt(1,16,3)';

To specify the data types interactively (by using the Data Type Assistant), use the Type Editor.

typeeditor

This example shows how to maintain the Simulink representations of C data types whose definitions you modify during the life of a modeling project.

Import Custom C Types

Create the file ex_cc_myTypes_rec.h in your current folder. The file defines a custom structure type.

typedef struct {
    double flow;
    double pres;
    double tqe;
} sigStructType;

Generate a Simulink.Bus object that represents the type.

Simulink.importExternalCTypes('ex_cc_myTypes_rec.h');

Modify Type Definition in C Code

In ex_cc_myTypes_rec.h, add a field named spd to sigStructType.

In the same file, create a new structure type, stateStructType.

typedef struct {
    double flow;
    double pres;
    double tqe;
    double spd;
} sigStructType;

typedef struct {
    double err;
    double read;
    double write;
} stateStructType;

Attempt to Import Types Again

Attempt to generate bus objects that represent the types.

importInfo = Simulink.importExternalCTypes('ex_cc_myTypes_rec.h');

The function generates warnings at the command prompt. Instead of relying on the warnings, you can inspect the output, importInfo, to determine whether the function failed to import any types.

importInfo.failedToImport.Bus
ans =

  1×1 cell array

    {'sigStructType'}

The function did not import sigStructType. The corresponding bus object in the base workspace still has only three bus elements. To determine the reason that the function did not import sigStructType, inspect the report field of importInfo.

Import sigStructType again. This time, overwrite the existing bus object.

importInfo = Simulink.importExternalCTypes('ex_cc_myTypes_rec.h',...
    'Names',importInfo.failedToImport.Bus,'Overwrite','on');

When you overwrite existing Simulink representations, any customizations that you made to the Simulink representations (such as the application of fixed-point data types to bus elements) are overwritten.

Input Arguments

collapse all

Names and paths of header files to parse, specified as a character vector, cell array of character vectors, string, or string array. Include the .h or .hpp file extension.

If you use a hierarchy of included (#include) header files to define your types, when you specify HeaderFiles, you need to identify only the entry-point files. The function parses the included files as well as the identified entry-point files. If the included files are not in the same folder as the corresponding entry-point file, use the IncludeDirs pair argument to identify the additional folders.

Example: 'myHeader.h'

Example: {'thisHeader.hpp','thatHeader.hpp'}

Data Types: char | cell | string

Name of a loaded Simulink model for which to import types, specified as a character vector or string scalar. A model is loaded if, for example, you open the model or use the load_system function. When you use this argument, the function:

  • Searches the model configuration parameters for custom header files and parses those header files for data types to import. Only the configuration parameters on the Simulation Target pane affect this search.

    For example, if in the model you set Configuration Parameters > Simulation Target > Include headers to #include "myTypes.h", the function parses myTypes.h for types to import.

  • Interprets generic C data types such as int or short according to the word lengths of your host computer. Do not use the HardwareImplementation pair argument to override this interpretation.

Example: 'myModel'

Data Types: char | string

Name-Value Arguments

Specify optional pairs of arguments as Name1=Value1,...,NameN=ValueN, where Name is the argument name and Value is the corresponding value. Name-value arguments must appear after other arguments, but the order of the pairs does not matter.

Before R2021a, use commas to separate each name and value, and enclose Name in quotes.

Example: Simulink.importExternalCTypes('myHdr.h','DataDictionary','myDictionary.sldd')

Name and, optionally, path of the MAT-file to create for storing generated Simulink.Bus and Simulink.AliasType objects, specified as a character vector or string. If you do not use MATFile, by default, the function generates the objects in the base workspace.

The function does not generate enumeration definitions in MAT-files.

If you import some struct types and primitive typedef statements by using MATFile and later import some of the same types again by using MATFile, the function entirely replaces the old MAT-file with a new one. The function discards any changes that you made to the contents of the old MAT-file.

You cannot use the MATFile and DataDictionary pair arguments simultaneously.

Example: 'myMat.mat'

Example: 'myMat'

Example: fullfile('subfolder','myMat')

Data Types: char | string

Name and, optionally, path of the Simulink data dictionary to use or create for storing generated enumerations and objects, specified as a character vector or string. When you use this pair argument, the function imports enumerated types as Simulink.data.dictionary.EnumTypeDefinition objects, and stores those objects (as well as Simulink.Bus objects and Simulink.AliasType objects) in the target dictionary.

For information about data dictionaries, see What Is a Data Dictionary?.

You can optionally specify a .sldd extension.

You cannot use the DataDictionary and MATFile pair arguments simultaneously.

Example: 'myDict.sldd'

Example: 'myDict'

Example: fullfile('subfolder','myDict.sldd')

Data Types: char | string

Names of types to import, specified as a character vector, cell array of character vectors, string, or string array. By default, if you do not use Names, the function attempts to import all of the custom types that the identified header files define.

To match multiple type names with a single character vector, use an asterisk (*).

Example: 'myEnumType'

Example: {'myEnumType','myStructType'}

Example: 'my*Type'

Data Types: char | cell | string

Compiler options to define macros that influence C type definitions, specified as a character vector, or string scalar. For example, a macro influences a type definition if you enclose the definition in an #ifdef block that checks whether the macro is defined.

Use Defines to specify macro definitions that you otherwise define through compiler options such as -D.

Example: 'SIGSTRUCT=1'

Example: 'SIGSTRUCT=1 ENUM=1'

Data Types: char | string

Compiler options to delete macros that influence C type definitions, specified as a character vector or string scalar. For example, a macro influences a type definition if you enclose the definition in an #ifdef block that checks whether the macro is defined.

Use UnDefines to specify macro deletions that you otherwise define through compiler options such as -U.

Example: 'SIGSTRUCT'

Example: 'SIGSTRUCT ENUM'

Data Types: char | string

Folders that contain subordinate, included (#include) header files, specified as a character vector, cell array of character vectors, string, or string array. Use this pair argument to enable the function to locate and parse additional header files on which the primary header files (which you specify with the headerFiles argument) depend.

If you use the modelName syntax instead of the headerFiles syntax, in the target model, you can use the Simulation Target configuration parameters to specify include paths. In that case, you do not need to use the IncludeDirs pair argument.

Example: 'myHeaders'

Example: fullfile('myProject','myHeaders')

Example: {fullfile('myProject','myHeaders'),fullfile('myProject','myOtherHeaders')}

Data Types: char | cell | string

Folder for storing generated files, specified as a character vector or string. The function places generated files, such as classdef script files and data dictionary files, in this folder.

The folder that you specify must exist before you use the function.

Example: 'myDictionaries'

Example: fullfile('myProject','myDictionaries')

Data Types: char | string

Parse and import compatible data types from C and C++ header files. If specify header files that contain C++ features, specify the Language to 'C++' to import compatible C data types.

When data types are imported from a header file with hpp extension, if the Language setting is not specified or set to 'Auto', 'C++' is selected to parse your header files. C++ classes and C++ struct types are ignored. Empty structs are not imported.

If you import header files from a loaded model and the Language is not specified or set to 'Auto', the Language setting is inherited from the model's custom settings. If the imported model already has a Language setting in Configuration Parameters > Simulation Target, this setting is overshadowed by imported model's setting.

Word lengths for interpreting generic, primitive C data types, specified as a Simulink.ConfigSet or coder.HardwareImplementation (MATLAB Coder) object.

  • To use a Simulink.ConfigSet object, you can extract a configuration set from a model by using functions such as getConfigSet and getActiveConfigSet. This technique enables you to use the Configuration Parameters dialog box to identify your target hardware (through the Hardware Implementation configuration parameters).

  • To use a coder.HardwareImplementation object (which you create and configure programmatically), specify properties of the object, such as ProdHWDeviceType, to identify your target hardware. The object then sets other properties, such as ProdBitPerInt, that reflect the native integer size of the hardware.

The function inspects the object to determine which Simulink integer data types to employ when interpreting generic C data types such as int. For example, if you create a coder.HardwareImplementation object to identify 16-bit hardware and then use the function to import a structure type whose fields use the C data type int, the function generates a bus object whose bus elements use the Simulink data type int16. The function uses the production hardware settings, not the test hardware settings.

For more information about hardware implementation settings for Simulink models, see Configure Run-Time Environment Options (Simulink Coder).

Specification to overwrite existing Simulink representations, specified as 'on' or 'off'. If an imported type already has a representation in Simulink:

  • If you specify 'off' or if you do not specify Overwrite, the function does not import the type. In the output argument, importInfo, the failedToImport field identifies the type.

  • If you specify 'on', the function overwrites the existing Simulink representation.

If you use the function to import some types into the base workspace or a data dictionary and later customize the generated Simulink representations, when you use the function again and set Overwrite to 'on', the function does not preserve your customizations. These customizations can include:

  • In an enumeration class definition, implementing extra methods or modifying the generated methods such as getDataScope (see Customize Simulink Enumeration).

  • Modifying the properties of a generated Simulink.Bus or Simulink.AliasType object (for example, manually setting the data types of bus elements to a fixed-point data type).

Specification to generate messages for successful import operations, specified as 'on' or 'off'.

  • If you specify 'off' or if you do not specify Verbose, the function imports types silently. Messages do not appear in the Command Window unless the function cannot import a type.

  • If you specify 'on', the function generates a message in the Command Window for each operation during the import process.

Output Arguments

collapse all

Information about types that were imported and not imported, returned as a structure with these fields.

Descriptions of types that were imported and not imported, returned as a character vector. Inspect the value of this field to determine the reason that the function could not import a type.

Types that were not imported, returned as a structure with these fields.

Field NameField ValuePurpose
BusCell array of character vectorsNames of structure (struct) types that were not imported.
EnumCell array of character vectorsNames of enumerated types (enum) that were not imported.
AliasTypeCell array of character vectorsNames of primitive typedef statements that were not imported.

Types that were successfully imported, returned as a structure with these fields.

Field NameField ValuePurpose
BusCell array of character vectorsNames of structure (struct) types that were imported. The generated Simulink.Bus objects use these names.
EnumCell array of character vectorsNames of enumerated types (enum) that were imported. The generated enumeration classes or Simulink.data.dictionary.EnumTypeDefinition objects use these names.
AliasTypeCell array of character vectorsNames of primitive typedef statements that were imported. The generated Simulink.AliasType objects use these names.

Limitations

  • The function does not support:

    • C data types that do not correspond to a type that Simulink supports. For example, Simulink does not recognize an equivalent for long double. For information about data types that Simulink supports, see Data Types Supported by Simulink.

    • Pointer types, such as a structure that defines a field whose value is a pointer or a typedef statement whose base type is a pointer type.

    • Unions.

  • If a structure field represents fixed-point data, or if a typedef statement maps to a fixed-point base type, the function sets the data type of the corresponding bus element or Simulink.AliasType object to the relevant Simulink integer type (such as int16). The importer cannot determine the fixed-point scaling by parsing the C code. After using the function, you must manually specify the data type of the bus element or the base type of the Simulink.AliasType object by using the fixdt function.

Tips

  • You must configure the Simulation Target configuration parameters for your model to include (#include) the header file which defines the imported enumeration or structure type in these cases:

    Note

    To import types that are not named in a typedef statement, ensure the Simulation Target configuration parameter Import custom code is selected. This parameter is selected by default.

  • By default:

    • For an imported enumeration, because the Simulink enumeration class derives from Simulink.IntEnumType, when you simulate or generate code from a model, the enumeration uses the integer size that is native to your target hardware. You specify the characteristics of your target hardware by using model configuration parameters such as Production device vendor and type and Native word size in production hardware.

    • For an imported structure type:

      • The function imports a structure field as numerically complex only if the field uses one of the corresponding Simulink Coder structure types as the data type. For example, if a structure field in your external code uses the data type cint8_T, the function imports the field as a bus element (Simulink.BusElement object) whose data type is int8 and whose Complexity property is set to 'complex'.

      • For nested structures, the function generates a bus object for each unique structure type.

    • For an imported structure or enumeration type, if your external code uses a typedef statement to name the type, the name of the generated bus object or Simulink enumeration class matches the typedef name. If your code does not use a typedef statement to name the type, the name of the object or class is the tag name of the type, unless that name conflicts with a type name that is defined in a typedef statement elsewhere in your header files, in which case the type is not imported into Simulink. If you do not specify a tag name or apply a typedef name, Simulink generates an arbitrary name for the object or class.

    • The function configures the generated Simulink representations as imported for the purposes of simulation and code generation. For example, for bus objects, the function sets the DataScope property to 'Imported' and the HeaderFile property to the name of your external header file. To simulate or generate code from a model that uses one of these Simulink representations, you must make your header file available to the model.

  • When you specify files for Simulink.importExternalCTypes to use or generate, for example, by using the DataDictionary pair argument:

    • If the existing files to use are in your current folder or on the MATLAB path, you do not need to specify a file path. You can specify the file name by itself.

    • To control the folder location of generated files, you can specify paths as well as file names. You can also use the OutputDir pair argument.

Version History

Introduced in R2017a