В этом примере показан процесс создания простого источника (.c или .cpp) и заголовок (.h), используя пример шаблона CFP. Затем выполняется анализ шаблона и кода, сгенерированного шаблоном.
Пример шаблона CFP, , демонстрирует некоторые возможности API шаблона кода, включаяmatlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc
Генерация простого источника (.c или .cpp) и заголовок (.h) файлы
Использование буферов для создания разделов файлов для includes, functions и т. д.
Генерация включает, определяет, в стандартные созданные файлы (например, )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 ®. Выберите активный набор конфигурации модели и откройте панель Создание кода (Code Generation) активного набора конфигурации.
На вкладке Шаблоны в поле Шаблон настройки файла укажите test_example_file_process.tlc. Это ранее отредактированный файл, который теперь является указанным шаблоном CFP для модели.
На вкладке Разное установите флажок Только генерировать код.
Нажмите кнопку «Применить».
В окне модели нажмите клавиши CTRL + B. Во время создания кода обратите внимание на следующее сообщение в программе Diagnostic Viewer:
Warning: Overriding example ert_main.c!
Это сообщение отображается, так как test_example_file_process.tlc генерирует основной программный модуль, переопределяющий действие по умолчанию для цели ERT. Это объясняется более подробно ниже.
rtwdemo_udt модель сконфигурирована для генерации отчета о создании кода HTML. После завершения создания кода просмотрите отчет.
Обратите внимание, что список «Сгенерированный код» содержит следующие файлы:
В разделе «Основной файл» ert_main.c.
В разделе «Другие файлы» 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.hLibGetMdlPubHdrBaseName чтобы получить имя для файл. Затем он получает ссылку на файл и генерирует определение в model.hDefines раздел :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 на основе настроек параметров Создать основную программу (Generate a example main program) и Целевая операционная система (Target operating system) на панели Шаблоны (Templates) диалогового окна Параметры конфигурации (Configuration Parameters). Шаблон CFP можно использовать для переопределения нормального поведения и создания основного программного модуля, настроенного для целевой среды.
Для поддержки формирования основных программных модулей предусмотрены два файла TLC:
bareboard_srmain.tlc: Код TLC для создания примера односкоростного основного программного модуля для целевой среды barebord. Код генерируется одной функцией TLC, FcnSingleTaskingMain.
bareboard_mrmain.tlc: Код TLC для создания многоскоростного основного программного модуля для целевой среды barebord. Код генерируется одной функцией TLC, FcnMultiTaskingMain.
В примере файл шаблона CFP , следующий код генерирует либо одно-, либо многозадачность matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlcert_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 функция для цели. A SelectCallback функция - это функция MATLAB, запускаемая при выполнении следующих действий:
Загрузите модель.
Обновите все настройки конфигурации в диалоговом окне «Параметры конфигурации».
Создайте модель.
Ваш SelectCallback функция должна отменить выбор и отключить параметр Generate a example main program. Это предотвращает использование переменной TLC GenerateSampleERTMain от установлено до TLC_TRUE.
См. раздел Структура rtwgensettings для получения информации о создании SelectCallback функция.
Следующий код иллюстрирует, как отменить выбор и отключить параметр Создать пример основной программы в контексте SelectCallback функция.
slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off'); slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0); hSrc.refreshDialog;
Примечание
Создание основной программы для целевой среды требует определенной настройки; например, в среде bareborand необходимо присоединить 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.tlctest_ для каждого файла) и обновите панель Шаблоны (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()>.
Пользовательские маркеры не поддерживаются при создании кода C++.