Generate Source and Header Files with a Custom File Processing (CFP) Template
This example shows you the process of generating a simple source (.c
or
.cpp
) and header (.h
) file using the example CFP
template. Then, it examines the template and the code generated by the template.
The example CFP template,
,
demonstrates some of the capabilities of the code template API, includingmatlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlc
Generation of simple source (
.c
or.cpp
) and header (.h
) filesUse of buffers to generate file sections for includes, functions, and so on
Generation of includes, defines, into the standard generated files (for example,
)model
.hGeneration of a main program module
Generate Code with a CFP Template
This section sets up a CFP template and configures a model to use the template in code
generation. The template generates (in addition to the standard model files) a source file
(timestwo.c
or .cpp
) and a header file
(timestwo.h
).
Follow the steps below to become acquainted with the use of CFP templates:
Copy the example CFP template,
, to a folder outside of the MATLAB® folder structure (that is, not undermatlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlc
). If the folder is not on the MATLAB path or the TLC path, then add it to the MATLAB path. It is good practice to locate the CFP template in the same folder as your system target file, which is on the TLC path.matlabroot
Rename the copied
example_file_process.tlc
totest_example_file_process.tlc
.Open
test_example_file_process.tlc
into the MATLAB editor.Uncomment the following line:
%% %assign ERTCustomFileTest = TLC_TRUE
It now reads:
%assign ERTCustomFileTest = TLC_TRUE
If
ERTCustomFileTest
is not assigned as shown, the CFP template is ignored in code generation.Save your changes to the file. Keep
test_example_file_process.tlc
open, so you can refer to it later.Open the
UserDefinedDataTypes
model.Open the Simulink® Model Explorer. Select the active configuration set of the model, and open the Code Generation pane of the active configuration set.
On the Templates tab, in the File customization template field, specify
test_example_file_process.tlc
. This is the file you previously edited and is now the specified CFP template for your model.On the General tab, select the Generate code only check box.
Click Apply.
In the model window, press Ctrl+B. During code generation, notice the following message in the Diagnostic Viewer:
Warning: Overriding example ert_main.c!
This message is displayed because
test_example_file_process.tlc
generates the main program module, overriding the default action of the ERT target. This is explained in greater detail below.The
UserDefinedDataTypes
model is configured to generate an HTML code generation report. After code generation is complete, view the report.Notice that the Generated Code list contains the following files:
Under Main file,
ert_main.c
.Under Other files,
timestwo.c
andtimestwo.h
.
The files were generated by the CFP template. The next section examines the template to learn how this was done.
Keep the model, the code generation report, and the
test_example_file_process.tlc
file open so you can refer to them in the next section.
Analysis of the Example CFP Template and Generated Code
This section examines excerpts from test_example_file_process.tlc
and
some of the code it generates. Refer to the comments in
while reading the following discussion.matlabroot
/rtw/c/tlc/mw/codetemplatelib.tlc
Generating Code Files
Source (.c
or .cpp
) and header
(.h
) files are created by calling
LibCreateSourceFile
, as in the following excerpts:
%assign cFile = LibCreateSourceFile("Source", "Custom", "timestwo") ... %assign hFile = LibCreateSourceFile("Header", "Custom", "timestwo")
Subsequent code refers to the files by the file reference returned from
LibCreateSourceFile
.
File Sections and Buffers
The code template API lets you partition the code generated to each file into
sections, tagged as Definitions
, Includes
,
Functions
, Banner
, and so on. You can append code
to each section as many times as required. This technique gives you a great deal of
flexibility in the formatting of your custom code files.
Subsections Defined for Built-In Sections describes the available file sections and their order in the generated file.
For each section of a generated file, use %openfile
and
%closefile
to store the text for that section in temporary buffers.
Then, to write (append) the buffer contents to a file section, call
LibSetSourceFileSection
, passing in the desired section tag and file
reference. For example, the following code uses two buffers (typesBuf
and tmpBuf
) to generate two sections (tagged
"Includes"
and "Functions"
) of the source file
timestwo.c
or .cpp
(referenced as
cFile
):
%openfile typesBuf #include "rtwtypes.h" %closefile typesBuf %<LibSetSourceFileSection(cFile,"Includes",typesBuf)> %openfile tmpBuf /* Times two function */ real_T timestwofcn(real_T input) { return (input * 2.0); } %closefile tmpBuf %<LibSetSourceFileSection(cFile,"Functions",tmpBuf)>
These two sections generate the entire timestwo.c
or
.cpp
file:
#include "rtwtypes.h" /* Times two function */ FLOAT64 timestwofcn(FLOAT64 input) { return (input * 2.0); }
Adding Code to Standard Generated Files
The timestwo.c
or .cpp
file generated in the
previous example was independent of the standard code files generated from a model (for
example,
or model
.c.cpp
,
, and so on). You can use similar
techniques to generate custom code within the model files. The code template API includes
functions to obtain the names of the standard models files and other model-related
information. The following excerpt calls model
.hLibGetMdlPubHdrBaseName
to
obtain the name for the
file. It
then obtains a file reference and generates a definition in the model
.hDefines
section of
:model
.h
%% Add a #define to the model's public header file model.h %assign pubName = LibGetMdlPubHdrBaseName() %assign modelH = LibCreateSourceFile("Header", "Simulink", pubName) %openfile tmpBuf #define ACCELERATION 9.81 %closefile tmpBuf %<LibSetSourceFileSection(modelH,"Defines",tmpBuf)>
Examine the generated UserDefinedDataTypes.h
file to see the
generated #define
directive.
Customizing Example Main Program Module Generation
ERT-based system target files determine whether and how to generate an example main
program module (ert_main.c
or ert_main.cpp
) based on
the settings of the model configuration parameters Generate an
example main program and Target operating system. You
can override the default behavior and generate a main
program
customized for your target environment.
Two TLC files support generation of an example main
program
module:
bareboard_srmain.tlc
: TLC code for generating a single-rate examplemain
program module for a bare-board target environment. TLC functionFcnSingleTaskingMain
generates the code.bareboard_mrmain.tlc
: TLC code for generating a multirate examplemain
program module for a bare-board target environment. TLC functionFcnMultiTaskingMain
generates the code.
In the example CFP template file
,
this code generates a single- or multitasking example matlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlcmain
program
module. The logic depends on information obtained from the code template calls to
LibIsSingleRateModel
and
LibIsSingleTasking
.
%% Create a simple main. Files are located in MATLAB/rtw/c/tlc/mw. %if LibIsSingleRateModel() || LibIsSingleTasking() %include "bareboard_srmain.tlc" %<FcnSingleTaskingMain()> %else %include "bareboard_mrmain.tlc" %<FcnMultiTaskingMain()> %endif
Files bareboard_srmain.tlc
and
bareboard_mrmain.tlc
use the code template programming interface to
generate the example main
program modules
ert_main.c
or ert_main.cpp
.
By default, the code generator produces an example main
program
module. To disable generation of that module, set the TLC variable
OverrideSampleERTMain
to TLC_TRUE
.
For example:
%if GenerateSampleERTMain %assign CompiledModel.OverrideSampleERTMain = TLC_TRUE %warning Overriding example ert_main.c! %endif
Alternatively, you can implement a SelectCallback
function for your
target. A SelectCallback
function is a MATLAB function that is
triggered when you:
Select a target by setting the System target file configuration parameter.
Build the model.
Your SelectCallback
clears the model configuration
parameter Generate an example main program. Clearing the
parameter prevents TLC variable GenerateSampleERTMain
from being set to
TLC_TRUE.
For information on how to create a SelectCallback
function, see
rtwgensettings Structure.
This code shows how to clear the Generate an example main
program parameter in the context of a SelectCallback
function.
slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off'); slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0); hSrc.getConfigSet.refreshDialog;
Creation of a main
program for your target environment requires
customization. For example, in a bare-board environment, you need to attach
rt_OneStep
to a timer interrupt and customize the generated code, the
generating TLC code, or both. For more information, see Guidelines for Modifying Main Program and Guidelines for Modifying rt_OneStep.
Generate a Custom Section
You can define custom tokens in a CGT file and
direct generated code into an associated built-in section. This feature gives you additional
control over the formatting of code within each built-in section. For example, you could add
subsections to built-in sections that do not already define subsections. Custom sections
must be associated with one of the built-in sections: Includes
,
Defines
, Types
, Enums
,
Definitions
, Declarations
, or
Functions
. To create custom sections, you must
Add a custom token to the code insertion section of your CGT file.
In your CFP file:
Assemble code to be generated to the custom section into a buffer.
Declare an association between the custom section and a built-in section, with the code template API function
LibAddSourceFileCustomSection
.Emit code to the custom section with the code template API function
LibSetSourceFileCustomSection
.
The following code examples illustrate the addition of a custom token,
Myincludes
, to a CGT file, and the subsequent association of the custom
section Myincludes
with the built-in section Includes
in a CFP file.
Note
If you have not already created custom CGT and CFP files for your model, copy the
default template files
and matlabroot
/toolbox/rtw/targets/ecoder/ert_code_template.cgt
to a work folder that is outside the MATLAB folder structure but on the MATLAB or TLC path, rename them (for example, add the prefix
matlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlctest_
to each file), and update the Templates
pane of the Configuration Parameters dialog box to reference them.
First, add the token Myincludes
to the code insertion section of your
CGT file. For example:
%<Includes> %<Myincludes> %<Defines> %<Types> %<Enums> %<Definitions> %<Declarations> %<Functions>
Next, in the CFP file, add code to generate include
directives into a
buffer. For example, in your copy of the example CFP file, you could insert the following
section between the Includes
section and the Create a simple
main
section:
%% Add a custom section to the model's C file model.c %openfile tmpBuf #include "moretables1.h" #include "moretables2.h" %closefile tmpBuf %<LibAddSourceFileCustomSection(modelC,"Includes","Myincludes")> %<LibSetSourceFileCustomSection(modelC,"Myincludes",tmpBuf)>
The LibAddSourceFileCustomSection
function call declares an
association between the built-in section Includes
and the custom section
Myincludes
. Myincludes
is a subsection of
Includes
. The LibSetSourceFileCustomSection
function
call directs the code in the tmpBuf
buffer to the
Myincludes
section of the generated file.
LibSetSourceFileCustomSection
is syntactically identical to
LibSetSourceFileSection
.
In the generated code, the include directives generated to the custom section appear
after other code directed to Includes
.
#include "UserDefinedDataTypes.h" #include "UserDefinedDataTypes_private.h" /* #include "mytables.h" */ #include "moretables1.h" #include "moretables2.h"
Note
The placement of the custom token in this example CGT file is arbitrary. By locating
%<Myincludes>
after %<Includes>
, the
CGT file specifies only that the Myincludes
code appears after
Includes
code.
Custom Tokens
Custom tokens are automatically translated to TLC syntax as a part of the build process.
To escape a token, that is to prepare it for normal TLC expansion, use the '!' character.
For example, the token %<!TokenName>
is expanded to
%<TokenName>
by the template conversion program. You can specify
valid TLC code, including TLC function calls:
%<!MyTLCFcn()>
.
Custom tokens are not supported when you generate C++ code.