Main Content

Write Code to Interact with Generated C API Signal and Parameter Code

In this step of the example, your external code uses the generated C API code to access model signals and model parameters.

Open the model CapiSigsParams.

capiMdl = "CapiSigsParams";
open_system(capiMdl);

Update Definition of realTimeCapiFcn

In the previous step you used the realTimeCapiFcn function to access metadata and real-time values model signals. In this step the realTimeCapiFcn function is used to access, in addition, metadata and real-time values model parameters. The function gets pointers to the signal array map and the data array address map. Then the function:

  1. Gets the number of model parameters and a pointer to the parameter array map. These are two fields in the Parameters structure, which is an inner structure in the static C API map.

  2. Uses the indices from the parameter array and the signal array to reference into the data address map to get pointers to the real-time values of the signals and parameters.

  3. Prints the signal and parameter names and their real-time values every 30th step of the model.

The source file CapiSigsParams_05.c contains the new definition of the function realTimeCapiFcn (and the same definitions of the initCapiFcn and cleanCapiFcn functions as in the source file from the previous step, CapiSigsParams_04.c).

To view the function definitions, examine the file CapiSigsParams_05.c. This is the realTimeCapiFcn function definition:

/** realTimeCapiFcn **
* Uses the C API to send the signal values to the monitor.
*/
int modelStep = 0; /* Use modelStep for the printing */
void realTimeCapiFcn()
{
  if(capiStage == 2)
  { /* The C API data structures are already terminated. */
    return;
  }

  int shouldPrint = !(modelStep%30);
  if(shouldPrint)
  {

    for(int idx=0 ; idx<sigCount ; idx++)
    {
      printf("step %0.3i: %s = %lf",modelStep,capiSigArr[idx].signalName,*((double*)sigPtrs[idx]));
      printf(" , ");
    }

    for(int idx=0 ; idx<mdlParamCount ; idx++)
    {
      printf("%s = %lf",capiMdlPrmArr[idx].varName,*((double*)mdlParamPtrs[idx]));
      if(idx < mdlParamCount-1)
      {
        printf(" , ");
      }
    }
    printf(".\n");
    fflush(0);
    usleep(500000);
  }
  modelStep++;
}
/* End realTimeCapiFcn */

The figure shows the relationships of the data structures in the realTimeCapiFcn function.

Schematic representation of model and C API data structures, and their inter-relations. The main C API model map is shown as a field in the real-time model object. A pointer to the static C API map is shown as a field in the main map. A pointer to the signal array is shown as a field in Signals, which is an inner structure of the static map. A pointer to the model parameters array is shown as a field in Parameters, which is an inner structure of the static map. A pointer to the primitive type data address array is shown as a field in InstanceMap, which is an inner structure of the main map. Indices that reference entries #0 and #1 in the data address array are shown as fields in entries #0 and #1 in the signal array, respectively, and indices that reference entries #2 and #3 in the data address array are shown as fields in entries #0 and #1 of the parameters array, respectively.

Update Custom Code Settings

In the Configuration Parameters dialog box, navigate to the Code Generation > Custom Code pane. On the Code Information tab, enter the path of the source file in the Source files box.

Configuration Parameters dialog box. The Code Generation > Custom Code pane is open. In the Code information tab of the Custom code settings section, the source file path is specified in the Source files box as CapiGetStartedFiles/CapiSigsParams_05.c

Click OK.

Alternatively, you can update the parameter programmatically by entering this command in the Command Window:

set_param(capiMdl,CustomSource="CapiSigsParamsFiles/CapiSigsParams_05.c")

Enable C API Generation for Parameters

To enable C API code generation for parameters:

  1. Open the Configuration Parameters dialog box.

  2. Navigate to the Code Generation > Interface pane.

  3. In the Data exchange interface > Generate C API for section, select parameters. Leave signals selected as well.

  4. Click OK.

Configuration Parameters dialog box. The Code Generation > Interface pane is open. In the Generate C API for section, the signals and parameters boxes are selected.

Alternatively, enter this in the Command Window:

set_param(capiMdl,RTWCAPIParams=true)

To prevent the code generator from optimizing the model parameters away, specify the default parameter behavior as Tunable. For more details, see Default parameter behavior.

  1. Open the Configuration Parameters dialog box.

  2. Navigate to the Code Generation > Optimization pane.

  3. From the Default parameter behavior list, select Tunable.

  4. Click Apply.

Configuration Parameters dialog box. The Code Generation > Optimization pane is open. From the Default parameter behavior list, Tunable is selected.

Alternatively, enter this in the Command Window:

set_param(capiMdl,DefaultParameterBehavior="Tunable")

Generate and Run Model Code

Use the slbuild command to generate code from your model. Use evalc to suppress the output of the slbuild command.

evalc("slbuild(capiMdl,GenerateCodeOnly=false)");

The code generator generates a standalone executable from the model. Use the system command to run this executable with the "-echo" input argument so that you can see the output of the model executable, with the printing from the exploreCapiModelElements function.

system(capiMdl,"-echo");
/bin/bash: line 1: CapiSigsParams: command not found

In the next step of the example your C code, that interacts with the generated C API code, uses a custom monitor to monitor model signals and tune model parameters. To continue to the next step of the example, use this in the Command Window:

openExample("simulinkcoder/CapiSigsParams06Example")