Main Content

Programmatically Customize C Functions Generated from Simulink Functions Scoped in Subsystems

In the generated model code, each Simulink function corresponds to one of the generated functions. The return value and input arguments of the generated function represent the Argument Inport blocks and Argument Outport blocks of the Simulink function, and the function body corresponds to the Simulink function logic.

A scoped Simulink® function is a Simulink Function block with the Function visibility parameter of its Trigger block specified as scoped. When a scoped Simulink function is nested inside a subsystem, it is callable from the subsystem it is located in and from any subsystem in its hierarchy. To read more about scoped Simulink functions in subsystems, see Scoped Simulink Function Blocks in Subsystems.

This example shows how to programmatically customize the name, return value, input arguments, and qualifier of a function generated from a scoped Simulink function nested inside a subsystem.

Tip: For this example, such Simulink functions are referred to as nested.

Load Model and Explore Nested Simulink Function Block

Load the model.

sfModel = "SimFuncs";
load_system(sfModel)

Verify that nestedSimFunc is a scoped Simulink Function block by getting the value of the Function visibility parameter of its Trigger block:

nestedSfTrig = "SimFuncs/subsystemWithSF/nestedSimFunc/n_func";
get_param(nestedSfTrig,"FunctionVisibility")
ans = 
'scoped'

Customize Generated Function Name and Argument Identifiers

You customize the names and argument identifiers of functions generated from nested Simulink functions (scoped inside any level of model hierarchy) by specifying the configuration parameters in the table. Specify each naming rule as a combination of valid C language characters and the available macros for the parameter. The specified naming rules apply to all nested Simulink functions in the model. Customizing names and argument identifiers of individual nested Simulink functions of the model is not supported.

Elements

Configuration Parameter

Available Macros

Programmatic Parameter Name

Function name

Subsystem methods

$F, $H, $M, $N, $R, and $U

For the definition of each macro,

see Subsystem methods.

CustomSymbolStrFcn

Argument identifiers

Subsystem method arguments

$I, $M, $N, and $U

For the definition of each macro,

see Subsystem method arguments .

CustomSymbolStrFcnArg

Specify the naming rule for the function name as custName_$N$M.

  • The macro $N is replaced by the Simulink Function block name.

  • The macro $M is required. It is replaced by an auto generated name-mangling text, required to avoid naming collisions. If there is no name collision, this macro is ignored.

Specify the naming rule for the argument identifiers as custArg_$I_$N$M.

  • The macro $I is replaced by the letter u for each input argument that corresponds to an Argument Inport block of the Simulink function, by the letter y for each input argument that corresponds to an Argument Outport block of the Simulink function, and by the letter pair uy for each combined input argument that corresponds to one Argument Inport block and one Argument Outport block of the Simulink function. For an example of using combined arguments, see Use Combined Inports and Outports.

  • The macro $N is replaced by the name of the Argument Inport block or Argument Outport block of the Simulink function.

  • The macro $M is required. It is replaced by an autogenerated name-mangling text to avoid naming collisions. If there is no name collision, this macro is ignored.

Use the set_param function to specify the naming rules:

set_param(sfModel,CustomSymbolStrFcn="custName_$N$M")
set_param(sfModel,CustomSymbolStrFcnArg="custArg_$I_$N$M")

Use the slbuild function to generate model code. Use the evalc function to suppress the output of the slbuild function.

evalc("slbuild(sfModel)");

Store the path to the generated source code file in srcFile. Then use the coder.example.extractLines function to see the customized function name and identifiers in the generated file.

srcFile = "SimFuncs_ert_rtw/SimFuncs.c";
coder.example.extractLines(srcFile,"n_func(",";",true,true);
void custName_n_func(real_T custArg_u_n_in1, real_T custArg_u_n_in2, real_T
                     *custArg_y_n_out1, real_T *custArg_y_n_out2);

The function name and argument identifiers adhere to the naming rules you specified.

Use Combined Inports and Outports

You can customize the generated function to have combined arguments, corresponding each to one Argument Inport block and one Argument Outport block of the Simulink function. A combined argument is passed by pointer, and is used in the generated function for both input and output. To use combined arguments, specify the same identifier for both the Argument Inport block and the Argument Outport block. In the example, update the Simulink function prototype with the argument n_in_out as the name of the first Argument Inport block and the name of the first Argument Outport block.

Store the new Simulink function prototype in the variable inOutPrototype, and store the paths to the Simulink function and to the Simulink function caller in the variables nestedSf and nestedSfCaller, respectively.

inOutPrototype = "[n_in_out,n_out2] = n_func(n_in_out,n_in2)";
nestedSf = "SimFuncs/subsystemWithSF/nestedSimFunc";
nestedSfCaller = "SimFuncs/subsystemWithSF/nestedSimFuncCaller";

Use the set_param function to update the Simulink function and its caller with the new prototype.

set_param(nestedSf,FunctionPrototype=inOutPrototype)
set_param(nestedSfCaller,FunctionPrototype=inOutPrototype)

Generate model code again:

evalc("slbuild(sfModel)");

Use the coder.example.extractLines function to see the customized function name and identifiers. This time, examine the function definition so you can see how the combined argument is used.

coder.example.extractLines(srcFile,"nestedSimFunc","}",true,true);
/* Output and update for Simulink Function: '<S3>/nestedSimFunc' */
void custName_n_func(real_T custArg_u_n_in2, real_T *custArg_uy_n_in_out, real_T
                     *custArg_y_n_out2)
{
  /* SignalConversion generated from: '<S4>/n_out2' incorporates:
   *  Gain: '<S4>/nGain2'
   *  Gain: '<S4>/nGain4'
   *  Gain: '<S4>/nGain6'
   *  SignalConversion generated from: '<S4>/n_in2'
   */
  *custArg_y_n_out2 = 27.0 * custArg_u_n_in2 * 10.0 * 2007.0;

  /* SignalConversion generated from: '<S4>/n_in_out~' incorporates:
   *  Gain: '<S4>/nGain1'
   *  Gain: '<S4>/nGain3'
   *  Gain: '<S4>/nGain5'
   */
  *custArg_uy_n_in_out = 28.0 * *custArg_uy_n_in_out * 6.0 * 2009.0;
}

In the definition of the generated function:

  • The macro $I, which you included in the specified naming rule for argument identifiers, is replaced by the letter pair uy for the combined argument.

  • The input argument custArg_uy_n_in_out is used for both input and output. Its value is used in the calculation and is being updated.

Customize Function Qualifiers

You can customize the qualifier of the generated function to be static or extern by enabling the configuration parameter for either qualifier.

Enable the parameter for extern by using the set_param function :

set_param(sfModel,PreserveExternInFcnDecls=true)

You can enable the qualifier for static in the same way:

set_param(sfModel,PreserveStaticInFcnDecls=true)

Note:

  • If both parameters are enabled, the code generator ignores the parameter for extern.

  • Customizing individual scoped Simulink functions in the model to use the static or extern qualifier is not supported.

Use the slbuild function again to generate code from the model:

evalc("slbuild(sfModel)");

Use the coder.example.extractLines function to see the generated function declaration.

coder.example.extractLines(srcFile,"n_func(",";",true,true);
extern void custName_n_func(real_T custArg_u_n_in2, real_T *custArg_uy_n_in_out,
  real_T *custArg_y_n_out2);

The function declaration has the extern qualifier.

See Also

| |

Topics