Этот пример показывает вам процесс генерации простого источника (.c
или .cpp
) и заголовок (.h
) файл с помощью шаблона CFP в качестве примера. Затем это исследует шаблон и код, сгенерированный шаблоном.
Шаблон CFP в качестве примера,
, демонстрирует некоторые возможности шаблона API кода, включаяmatlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc
Генерация простого источника (.c
или .cpp
) и заголовок (.h
) файлы
Использование буферов, чтобы сгенерировать разделы файлов для включает, функции, и так далее
Генерация включает, задает, в сгенерированные файлы стандарта (например,
)model.h
Генерация основного программного модуля
Этот раздел настраивает шаблон CFP и конфигурирует модель, чтобы использовать шаблон в генерации кода. Шаблон генерирует (в дополнение к стандартным образцовым файлам) исходный файл (timestwo.c
или .cpp
) и заголовочный файл (timestwo.h
).
Выполните шаги ниже, чтобы познакомиться с использованием шаблонов CFP:
Скопируйте шаблон CFP в качестве примера,
, к папке за пределами структуры папок MATLAB® (то есть, не под matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc
). Если папка не находится на пути MATLAB или пути TLC, то добавьте его в путь MATLAB. Это - хорошая практика, чтобы определить местоположение шаблона CFP в той же папке как ваш системный конечный файл, который находится на пути TLC.matlabroot
Переименуйте скопированный example_file_process.tlc
к test_example_file_process.tlc
.
Откройте test_example_file_process.tlc
в редактора MATLAB.
Не прокомментируйте следующую строку:
%% %assign ERTCustomFileTest = TLC_TRUE
Это теперь читает:
%assign ERTCustomFileTest = TLC_TRUE
Если ERTCustomFileTest
не присвоен как показано, шаблон CFP проигнорирован в генерации кода.
Сохраните свои изменения в файле. Сохраните test_example_file_process.tlc
открытым, таким образом, можно обратиться к нему позже.
Откройте модель rtwdemo_udt
.
Откройте Simulink® Model Explorer. Выберите активную конфигурацию модели модели и откройте панель Code Generation активной конфигурации модели.
На вкладке Templates, в поле File customization template, задают test_example_file_process.tlc
. Это - файл, который вы ранее отредактировали и являетесь теперь заданным шаблоном CFP для своей модели.
На вкладке General установите флажок Generate code only.
Нажмите Apply.
В окне модели нажмите Ctrl+B. Во время генерации кода заметьте следующее сообщение в Diagnostic Viewer:
Warning: Overriding example ert_main.c!
Это сообщение отображено, потому что test_example_file_process.tlc
генерирует основной программный модуль, заменяя действие по умолчанию цели ERT. Это объяснено более подробно ниже.
Модель rtwdemo_udt
сконфигурирована, чтобы сгенерировать отчет генерации кода HTML. После того, как генерация кода завершена, просмотрите отчет.
Заметьте, что список Generated Code содержит следующие файлы:
Под Main file, ert_main.c
.
Под Other files, timestwo.c
и timestwo.h
.
Файлы были сгенерированы шаблоном CFP. Следующий раздел исследует шаблон, чтобы изучить, как это было сделано.
Сохраните модель, отчет генерации кода и файл test_example_file_process.tlc
открытыми, таким образом, можно обратиться к ним в следующем разделе.
Этот раздел исследует выборки от test_example_file_process.tlc
и часть кода, который это генерирует. Обратитесь к комментариям в
при чтении следующего обсуждения.matlabroot/rtw/c/tlc/mw/codetemplatelib.tlc
Источник (.c
или .cpp
) и заголовок (.h
) файлы создается путем вызова LibCreateSourceFile
, как в следующих выборках:
%assign cFile = LibCreateSourceFile("Source", "Custom", "timestwo") ... %assign hFile = LibCreateSourceFile("Header", "Custom", "timestwo")
Последующий код относится к файлам ссылкой на файл, возвращенной в LibCreateSourceFile
.
Шаблон API кода позволяет вам разделить код, сгенерированный к каждому файлу в разделы, помеченные как Definitions
, Includes
, Functions
, Banner
, и так далее. Можно добавить код к каждому разделу так же много раз как требуется. Этот метод дает вам большую гибкость в форматировании ваших файлов пользовательского кода.
Подразделы, Заданные для Встроенных Разделов, описывают доступные разделы файлов и их порядок в сгенерированном файле.
Для каждого раздела сгенерированного файла используйте %openfile
и %closefile
, чтобы сохранить текст для того раздела во временных буферах. Затем чтобы записать (добавляют) содержимое буфера к разделу файла, вызывают LibSetSourceFileSection
, передающий в желаемом теге раздела и ссылке на файл. Например, следующий код использует два буфера (typesBuf
, и tmpBuf
), чтобы сгенерировать два раздела (пометил "Includes"
и "Functions"
) исходного файла timestwo.c
или .cpp
(ссылаемый как 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)>
Эти два раздела генерируют целый timestwo.c
или файл .cpp
:
#include "rtwtypes.h" /* Times two function */ FLOAT64 timestwofcn(FLOAT64 input) { return (input * 2.0); }
Файл timestwo.c
или .cpp
, сгенерированный в предыдущем примере, был независим от стандартных файлов кода, сгенерированных из модели (например,
или model.c
.cpp
,
, и так далее). Можно использовать подобные методы, чтобы сгенерировать пользовательский код в образцовых файлах. Шаблон API кода включает функции, чтобы получить имена стандартных файлов моделей и другой связанной с моделью информации. Следующая выборка вызывает model.h
LibGetMdlPubHdrBaseName
, чтобы получить имя для файла
. Это затем получает ссылку на файл и генерирует определение в разделе model.h
Defines
: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)>
Исследуйте сгенерированный файл rtwdemo_udt.h
, чтобы видеть сгенерированную директиву #define
.
Обычно, цель ERT определяет, ли и как сгенерировать ert_main.c
или модуль .cpp
на основе настроек Того, чтобы генерировать пример основная программа и опции Target operating system на панели Templates диалогового окна Configuration Parameters. Можно использовать шаблон CFP, чтобы заменить нормальное поведение и сгенерировать основной программный модуль, настроенный для целевого окружения.
Чтобы поддержать генерацию основных программных модулей, два файла TLC обеспечиваются:
bareboard_srmain.tlc
: код TLC, чтобы сгенерировать пример односкоростной основной программный модуль для целевого окружения несмонтированной платы. Код сгенерирован одной функцией TLC, FcnSingleTaskingMain
.
bareboard_mrmain.tlc
: код TLC, чтобы сгенерировать многоскоростной основной программный модуль для целевого окружения несмонтированной платы. Код сгенерирован одной функцией TLC, FcnMultiTaskingMain
.
В файле шаблона CFP в качестве примера
следующий код генерирует или сингл - или многозадачный matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc
ert_main.c
или модуль .cpp
. Логика зависит от информации, полученной из вызовов API шаблона кода LibIsSingleRateModel
и 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
Обратите внимание на то, что bareboard_srmain.tlc
и bareboard_mrmain.tlc
используют шаблон API кода, чтобы сгенерировать ert_main.c
или .cpp
.
При генерации собственного основного программного модуля вы отключаете генерацию по умолчанию ert_main.c
или .cpp
. Переменная TLC GenerateSampleERTMain
управляет генерацией ert_main.c
или .cpp
. Можно непосредственно обеспечить эту переменную к TLC_FALSE
. Примеры bareboard_mrmain.tlc
и bareboard_srmain.tlc
используют этот метод, как показано в следующей выборке от bareboard_srmain.tlc
.
%if GenerateSampleERTMain %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE %warning Overriding example ert_main.c! %endif
Также можно реализовать функцию SelectCallback
для цели. Функцией SelectCallback
является функция MATLAB, которая инициирована когда вы:
Загрузите модель.
Обновите любые параметры конфигурации в диалоговом окне Configuration Parameters.
Создайте модель.
Ваша функция SelectCallback
должна отменить выбор и отключить Генерировать пример основная опция программы. Это предотвращает переменную TLC GenerateSampleERTMain
от того, чтобы быть установленным до TLC_TRUE.
Смотрите раздел Structure (Simulink Coder) rtwgensettings для получения информации о создании функции SelectCallback
.
Следующий код иллюстрирует, как отменить выбор и отключить Генерировать пример основная опция программы в контексте функции SelectCallback
.
slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off'); slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0);
Создание основной программы для вашего целевого окружения требует некоторой индивидуальной настройки; например, в среде несмонтированной платы необходимо присоединить rt_OneStep
к прерыванию по таймеру. Ожидается, что вы настроите или сгенерированный код, генерация код TLC, или обоих. См. Инструкции для Изменения Основной Программы и Инструкций для Изменения rt_OneStep для получения дополнительной информации.
Можно задать пользовательские лексемы в файле CGT и прямом сгенерированном коде в связанный встроенный раздел. Эта функция дает вам дополнительный контроль над форматированием кода в каждом встроенном разделе. Например, вы могли добавить подразделы во встроенные разделы, которые уже не задают подразделы. Пользовательские разделы должны быть сопоставлены с одним из встроенных разделов: Includes
, Defines
, Types
, Enums
, Definitions
, Declarations
или Functions
. Чтобы создать пользовательские разделы, вы должны
Добавьте пользовательскую лексему в раздел вставки кода вашего файла CGT.
В вашем файле CFP:
Соберите код, который будет сгенерирован к пользовательскому разделу в буфер.
Объявите, что ассоциация между пользовательским разделом и встроенным разделом, с кодом обрабатывают API-функцию по шаблону LibAddSourceFileCustomSection
.
Испустите код к пользовательскому разделу с API-функцией шаблона кода LibSetSourceFileCustomSection
.
Следующие примеры кода иллюстрируют сложение пользовательской лексемы, Myincludes
, к файлу CGT и последующей ассоциации пользовательского раздела Myincludes
со встроенным разделом Includes
в файле CFP.
Если вы уже не создали пользовательский CGT и файлы CFP для вашей модели, скопируйте файлы шаблона по умолчанию
и matlabroot/toolbox/rtw/targets/ecoder/ert_code_template.cgt
к папке работы, которая является вне структуры папок MATLAB, но на MATLAB или пути TLC, переименуйте их (например, добавьте префиксный matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc
test_
в каждый файл), и обновите панель Templates диалогового окна Configuration Parameters, чтобы сослаться на них.
Во-первых, добавьте маркерный Myincludes
в раздел вставки кода вашего файла CGT. Например:
%<Includes> %<Myincludes> %<Defines> %<Types> %<Enums> %<Definitions> %<Declarations> %<Functions>
Затем, в файле CFP, добавьте код, чтобы сгенерировать директивы include
в буфер. Например, в вашей копии файла CFP в качестве примера, вы могли вставить следующий раздел между разделом Includes
и разделом Create a simple main
:
%% 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)>
Вызов функции LibAddSourceFileCustomSection
объявляет ассоциацию между встроенным разделом Includes
и пользовательским разделом Myincludes
. Myincludes
является подразделом Includes
. Вызов функции LibSetSourceFileCustomSection
направляет код в буфере tmpBuf
к разделу Myincludes
сгенерированного файла. LibSetSourceFileCustomSection
синтаксически идентичен LibSetSourceFileSection
.
В сгенерированном коде появляются включать директивы, сгенерированные к пользовательскому разделу после того, как другой код направил к Includes
.
#include "rtwdemo_udt.h" #include "rtwdemo_udt_private.h" /* #include "mytables.h" */ #include "moretables1.h" #include "moretables2.h"
Размещение пользовательской лексемы в этом примере файл CGT произвольно. Путем определения местоположения %<Myincludes>
после %<Includes>
файл CGT указывает только, что код Myincludes
появляется после кода Includes
.
Пользовательские лексемы автоматически переводятся в синтаксис TLC как часть процесса сборки. Выйти из лексемы, которая должна подготовить его к нормальному расширению TLC, использованию'! Символ. Например, маркерный %<!TokenName>
расширен до %<TokenName>
программой преобразования шаблона. Можно задать допустимый код TLC, включая вызовы функции TLC: %<!MyTLCFcn()>
.