Сгенерируйте исходные и заголовочные файлы с шаблоном Пользовательской обработки файла (CFP)

Этот пример показывает вам процесс генерации простого источника (.c или .cpp) и заголовок (.h) файл с помощью шаблона CFP в качестве примера. Затем это исследует шаблон и код, сгенерированный шаблоном.

Шаблон CFP в качестве примера, matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc, демонстрирует некоторые возможности шаблона API кода, включая

  • Генерация простого источника (.c или .cpp) и заголовок (.h) файлы

  • Использование буферов, чтобы сгенерировать разделы файлов для включает, функции, и так далее

  • Генерация включает, задает, в сгенерированные файлы стандарта (например, modelH)

  • Генерация основного программного модуля

Сгенерируйте код с шаблоном CFP

Этот раздел настраивает шаблон CFP и конфигурирует модель, чтобы использовать шаблон в генерации кода. Шаблон генерирует (в дополнение к стандартным файлам модели) исходный файл (timestwo.c или .cpp) и заголовочный файл (timestwo.h).

Выполните шаги ниже, чтобы познакомиться с использованием шаблонов CFP:

  1. Скопируйте шаблон CFP в качестве примера, matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc, к папке за пределами структуры папок MATLAB® (то есть, не под matlabroot). Если папка не находится на пути MATLAB или пути TLC, то добавьте его в путь MATLAB. Это - хорошая практика, чтобы определить местоположение шаблона CFP в той же папке как ваш системный конечный файл, который находится на пути TLC.

  2. Переименуйте скопированный example_file_process.tlc к test_example_file_process.tlc.

  3. Открытый test_example_file_process.tlc в редактор MATLAB.

  4. Не прокомментируйте следующую линию:

    %%  %assign ERTCustomFileTest = TLC_TRUE

    Это теперь читает:

      %assign ERTCustomFileTest = TLC_TRUE

    Если ERTCustomFileTest не присвоен как показано, шаблон CFP проигнорирован в генерации кода.

  5. Сохраните свои изменения в файле. Сохраните test_example_file_process.tlc открытый, таким образом, можно обратиться к нему позже.

  6. Откройте rtwdemo_udt модель.

  7. Откройте Simulink® Model Explorer. Выберите активную конфигурацию модели модели и откройте панель Code Generation активной конфигурации модели.

  8. На вкладке Templates, в поле File customization template, задают test_example_file_process.tlc. Это - файл, который вы ранее отредактировали и являетесь теперь заданным шаблоном CFP для своей модели.

  9. На вкладке General установите флажок Generate code only.

  10. Нажмите Apply.

  11. В окне модели нажмите Ctrl+B. Во время генерации кода заметьте следующее сообщение в Diagnostic Viewer:

    Warning:  Overriding example ert_main.c!
    

    Это сообщение отображено потому что test_example_file_process.tlc генерирует основной программный модуль, заменяя действие по умолчанию цели ERT. Это объяснено более подробно ниже.

  12. rtwdemo_udt модель сконфигурирована, чтобы сгенерировать отчет генерации кода HTML. После того, как генерация кода завершена, просмотрите отчет.

    Заметьте, что список Generated Code содержит следующие файлы:

    • Под Main file, ert_main.c.

    • Под Other files, timestwo.c и timestwo.h.

    Файлы были сгенерированы шаблоном CFP. Следующий раздел исследует шаблон, чтобы изучить, как это было сделано.

  13. Сохраните модель, отчет генерации кода и test_example_file_process.tlc файл, открытый, таким образом, можно обратиться к ним в следующем разделе.

Анализ шаблона кода CFP в качестве примера и сгенерированного кода

Этот раздел исследует выборки от 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Функции, 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 файл, сгенерированный в предыдущем примере, был независим от стандартных файлов кода, сгенерированных из модели (например, modelC или .cpp, modelH, и так далее). Можно использовать подобные методы, чтобы сгенерировать пользовательский код в файлах модели. Шаблон API кода включает функции, чтобы получить имена стандартных файлов моделей и другой связанной с моделью информации. Следующая выборка вызывает LibGetMdlPubHdrBaseName получить имя для modelH файл. Это затем получает ссылку на файл и генерирует определение в Defines раздел modelH:

%% 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 rtwgensettings для получения информации о создании SelectCallback функция.

Следующий код иллюстрирует, как отменить выбор и отключить Генерировать пример основная опция программы в контексте SelectCallback функция.

slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off');
slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0);
hSrc.refreshDialog;

Примечание

Создание основной программы для вашего целевого окружения требует некоторой индивидуальной настройки; например, в среде несмонтированной платы необходимо присоединить rt_OneStep к прерыванию по таймеру. Ожидается, что вы настроите или сгенерированный код, генерация код TLC, или обоих. См. Инструкции для Изменения Основной Программы и Инструкций для Изменения rt_OneStep для получения дополнительной информации.

Сгенерируйте пользовательский раздел

Можно задать пользовательские лексемы в файле CGT и прямом сгенерированном коде в связанный встроенный раздел. Эта функция дает вам дополнительный контроль над форматированием кода в каждом встроенном разделе. Например, вы могли добавить подразделы во встроенные разделы, которые уже не задают подразделы. Пользовательские разделы должны быть сопоставлены с одним из встроенных разделов: Includes, Defines, Types, EnumsОпределения, Declarations, или Functions. Чтобы создать пользовательские разделы, вы должны

  • Добавьте пользовательскую лексему в раздел вставки кода вашего файла CGT.

  • В вашем файле CFP:

    • Соберите код, который будет сгенерирован к пользовательскому разделу в буфер.

    • Объявите, что ассоциация между пользовательским разделом и встроенным разделом, с кодом обрабатывают API-функцию по шаблону LibAddSourceFileCustomSection.

    • Испустите код к пользовательскому разделу с API-функцией шаблона кода LibSetSourceFileCustomSection.

Следующие примеры кода иллюстрируют сложение пользовательской лексемы, Myincludes, к файлу CGT и последующей ассоциации пользовательского раздела Myincludes со встроенным разделом Includes в файле CFP.

Примечание

Если вы уже не создали пользовательский CGT и файлы CFP для вашей модели, скопируйте файлы шаблона по умолчанию matlabroot/toolbox/rtw/targets/ecoder/ert_code_template.cgt и matlabroot/toolbox/rtw/targets/ecoder/example_file_process.tlc к папке работы, которая находится вне структуры папок MATLAB, но на MATLAB или пути 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()>.