wrapper Обзор учебного пособияЦель: Узнайте архитектуру оберточных S-функций и как создать встроенную оберточную S-функцию с помощью TLC.
Папка:
(открыто)matlabroot/toolbox/rtw/rtwdemos/tlctutorial/wrapper
Обертка S-функций позволяет использовать существующие C-функции без их полной перезаписи в контексте Simulink ® S-функций. Каждая предоставленная оболочка представляет собой «оболочку» S-функции, которая просто вызывает одну или несколько существующих внешних функций. В данном учебном пособии поясняются и иллюстрируются обертки следующим образом:
Зачем переносить код пользователя? - Причина создания функций оболочки TLC
Начало работы - настройка упражнения обертки
Генерировать код без обертки - как генератор кода обрабатывает внешние функции по умолчанию
Создание кода с помощью обертки - обход заголовка API
Многие пользователи Simulink хотят построить модели, включающие алгоритмы, которые они уже закодировали, внедрили и протестировали на языке высокого уровня. Обычно такой код вводится в Simulink как S-функции. Для создания внешнего приложения, интегрирующего пользовательский код, можно использовать несколько подходов:
Можно создать S-функцию из кода пользователя, который подключает ее к универсальному API Simulink. Это простейший подход, но жертвует эффективностью для автономных приложений.
Можно встроить S-функцию, повторно воплотив ее в файл TLC. Это повышает эффективность, но требует времени и усилий, может вводить ошибки в рабочий код и приводит к двум наборам кода для поддержания для каждого алгоритма, если только не используется устаревший инструмент кода (см. Импорт вызовов внешнего кода в сгенерированный код с устаревшим инструментом кода).
S-функцию можно встроить с помощью функции оболочки TLC. При этом необходимо создать лишь небольшое количество кода TLC, и алгоритм может оставаться закодированным в существующем виде.
На следующем рисунке показано, как работают оболочки S-функций.

Перенос функции устраняет необходимость ее перекодирования, требуя только бит дополнительного кода TLC для ее интеграции. Оболочки также позволяют использовать объектные модули или библиотеки в S-функциях. Это может быть единственным способом развертывания функций, для которых исходный код недоступен, а также позволяет пользователям распространять модели другим пользователям без разглашения сведений о реализации, которые могут быть запатентованы.
Например, существует файл объекта, скомпилированный для процессора, на котором Simulink не выполняется. Можно написать фиктивную C S-функцию и использовать оболочку TLC, которая вызывает внешнюю функцию, несмотря на отсутствие ее исходного кода. Аналогичным образом можно получить доступ к функциям в библиотеке алгоритмов, оптимизированных для целевого процессора. Для этого необходимо внести изменения в файл шаблона или иным образом предоставить средство связи с библиотекой.
Примечание
Файлы объектов, в которых отсутствует исходный код и которые создаются с помощью Microsoft ® Visual C и Microsoft Visual C++ (MSVC), работают только с MSVC.
Единственное ограничение на оболочки S-функций заключается в количестве входов и выходов блоков, соответствующих количеству входов и выходов обернутой внешней функции. Код обертки может включать в себя вычисления, но обычно они ограничиваются преобразованием значений (например, масштабированием или переформатированием), передаваемых в и из обернутых внешних функций.
В папке примера «внешняя функция» находится в файле my_alg.c. Также предоставляется C S-функция, называемая wrapsfcn.c который интегрирует my_alg.c в Simulink. Настройте упражнение следующим образом:
Сделать tlctutorial/wrapper текущая папка.
Откройте модель в MATLAB ®externalcode из рабочей папки. Блок-схема выглядит следующим образом:

Активируйте блок «Область», дважды щелкнув его.
Запустите модель (на вкладке «Моделирование» или введите Ctrl + T). Вы получите сообщение об ошибке wrapsfcn не существует. Ты можешь понять почему?
Ошибка возникает из-за mex файл не существует для wrapsfcn. Чтобы исправить это, в поле MATLAB Command Window введите
mex wrapsfcn.c
Примечание
Ошибка может возникнуть, если вы ранее не запускали mex -setup.
Снова запустите моделирование с использованием S-функции.
Блок S-Function умножает свой вход на два. В блоке Scope отображается синусоидальная волна, колеблющаяся между -2.0 и 2.0. Переменная yout , которая создается в рабочей области MATLAB с помощью этих значений.
В оставшейся части упражнения вы создадите и запустите автономную версию модели, а затем напишите некий код TLC, который позволит генератору кода построить автономный исполняемый файл, вызывающий S-функцию. my_alg.c непосредственно.
Перед созданием оболочки создайте код, использующий общий API Simulink. Первым шагом является создание автономной модели.
На вкладке C Code нажмите кнопку Build.
Генератор кода создает автономную программу в рабочей папке и помещает исходные файлы и файлы объектов в папку построения. Файл будет вызван externalcode.exe на платформах Microsoft Windows ® илиexternalcode на платформах UNIX ®.
При создании программы генератор кода сообщает о ходе выполнения в окне команд MATLAB. Окончательные строки:
### Created executable: externalcode.exe ### Successful completion of build procedure for model: externalcode
Запустите автономную программу, чтобы убедиться, что она ведет себя так же, как и версия Simulink. Различий быть не должно.
!externalcode ** starting the model ** ** created externalcode.mat **
Обратите внимание на эту строку в wrapsfcn.c:
#include "my_alg.c"
Это позволяет использовать внешнюю функцию. Эта функция полностью состоит из
/*
* Copyright 1994-2002 The MathWorks, Inc.
*/
double my_alg(double u)
{
return(u * 2.0);
}Осмотрите mdlOutputs() функция кода в wrapsfcn.c для просмотра способа вызова внешней функции.
static void mdlOutputs(SimStruct *S, int tid)
{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
int_T width = ssGetOutputPortWidth(S,0);
*y = my_alg(*uPtrs[0]);
}Совет
Для платформ UNIX запустите исполняемую программу в окне команд с синтаксисом !./executable_name. При необходимости запустите исполняемую программу из оболочки ОС с синтаксисом ./executable_name. Дополнительные сведения см. в разделе Запуск внешних команд, сценариев и программ.
Как правило, функции, подлежащие переносу, либо включаются в оболочку, как описано выше, либо, когда объектные модули переносятся, разрешаются во время соединения.
Создание оболочки для внешней функции my_alg.c, необходимо создать файл TLC, который воплощает его вызывающую функцию, wrapsfcn.c. Файл TLC должен генерировать код C, который обеспечивает:
Прототип функции для внешней функции, которая возвращает двойное значение и передает входные данные double u.
Вызов функции my_alg() в разделе выходных данных кода.
Создание обертки для my_alg(), выполните следующие действия:
Открыть файл change_wrapsfcn.tlc в редакторе и добавьте строки кода, где комментарии указывают на создание рабочей оболочки.
Сохранить отредактированный файл как wrapsfcn.tlc. Он должен иметь то же имя, что и S-функциональный блок, который его использует, или TLC не вызывается для встроенного кода.
В MATLAB откройте модель. externalcode из рабочей папки. Активируйте блок «Область», дважды щелкнув его, и запустите модель (на вкладке «Моделирование» или введите Ctrl + T). Это дает базовый результат.
Сообщите Simulink, что код имеет внешнюю ссылку для разрешения. Чтобы обновить параметры модели, в окне команды MATLAB выполните одно из следующих действий.
Напечатать
set_param('externalcode/S-Function','SFunctionModules','my_alg')В диалоговом окне «S-Function block parameters» (Параметры S-функционального блока) в диалоговом окне S-function modules поле, укажите 'my_alg'.
Создайте автономное приложение, введя одну из следующих команд в окне команд:
slbuild('my_alg','ForceTopModelBuild',true)
slbuild('my_alg', 'StandaloneCoderTarget','ForceTopModelBuild',true)
Эти команды заставляют генератор кода перестроить модель верхнего уровня, что требуется при внесении изменений, связанных с внешним или пользовательским кодом.
Кроме того, можно принудительно выполнить регенерацию кода модели верхнего уровня, удалив папки в папке создания кода, например slprj или созданную папку кода модели.
Дополнительные сведения см. в разделе Управление регенерацией кода верхней модели.
Запустите новое автономное приложение и убедитесь, что оно дает те же результаты, что и в окне области.
!externalcode
При возникновении проблем при создании приложения:
Найдите сообщения об ошибках и попробуйте определить, какие файлы неисправны, обращая внимание на то, какой шаг (создание кода, компиляция, связывание) не удался.
Убедитесь, что вы выпустили set_param() как указано выше.
Скорее всего, проблемы можно отследить в файле TLC. Может быть полезно использовать отладчик TLC для выполнения шагов wrapsfcn.tlc.
В крайнем случае, посмотрите на wrapsfcn.tlc в solutions/tlc_solution папка, также перечисленная ниже:
%% File : wrapsfcn.tlc %% Abstract: %% Example tlc file for S-function wrapsfcn.c %% %% Copyright 1994-2002 The MathWorks, Inc. %% %% %implements "wrapsfcn" "C"
%% Function: BlockTypeSetup ================================ %% Abstract: %% Create function prototype in model.h as: %% "extern double my_alg(double u);" %% %function BlockTypeSetup(block, system) void %openfile buffer %% ASSIGNMENT: PROVIDE A LINE OF CODE AS A FUNCTION PROTOTYPE %% FOR "my_alg" AS DESCRIBED IN THE WRAPPER TLC ASSIGNMENT extern double my_alg(double u); %closefile buffer %<LibCacheFunctionPrototype(buffer)> %endfunction %% BlockTypeSetup
%% Function: Outputs ======================================= %% Abstract: %% y = my_alg( u ); %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %assign u = LibBlockInputSignal(0, "", "", 0) %assign y = LibBlockOutputSignal(0, "", "", 0) %% PROVIDE THE CALLING STATEMENT FOR "wrapfcn" %<y> = my_alg( %<u> ); %endfunction %% Outputs
Посмотрите на выделенные линии. Вы заявили my_alg() как extern double? Вы звонили my_alg() с ожидаемыми входными и выходными данными? Исправьте ошибки и восстановите модель.