wrapper
Objective: Изучает архитектуру S-функций обертки и как создать встроенную S-функцию обертки с помощью TLC.
Folder: (открытый)
matlabroot/toolbox/rtw/rtwdemos/tlctutorial/wrapper
S-функции обертки позволяют вам использовать существующие функции C, полностью не переписывая их в контексте S-функций Simulink®. Каждой оберткой, которую вы обеспечиваете, является S-функция “интерпретатор”, который просто вызывает одну или несколько существующих, внешних функций. Этот пример объясняет и иллюстрирует обертки можно следующим образом:
Why Wrap User Code? — Причина создания функций обертки TLC
Начало работы Настройте осуществление обертки
Generate Code Without a Wrapper — Как генератор кода обрабатывает внешние функции по умолчанию
Generate Code Using a Wrapper — Обойдите API наверху
Многие пользователи Simulink хотят создать, моделирует соединяющиеся алгоритмы, которые они уже закодировали, реализовали и протестировали в высокоуровневом языке. Как правило, такой код принесен в Simulink как S-функции. Чтобы сгенерировать внешнее приложение, которое интегрирует пользовательский код, можно проявить несколько подходов:
Можно создать S-функцию из пользовательского кода, который сцепляет ее с Simulink типичный API. Это - самый простой подход, но жертвует эффективностью за автономные приложения.
Можно встроить S-функцию, повторно реализовав его как файл TLC. Это повышает эффективность, но занимает время и усилие, может ввести ошибки в рабочий код и приводит к двум наборам кода, чтобы поддержать для каждого алгоритма, если вы не используете Legacy Code Tool (см. Вызовы Импорта Внешнего Кода в Сгенерированный код с Legacy Code Tool).
Можно встроить S-функцию через wrapper function TLC. Путем выполнения так, необходимо создать только небольшое количество кода TLC, и алгоритм может остаться закодированным в своей существующей форме.
Следующая фигура иллюстрирует, как обертки S-функции действуют.
Перенос функции избавляет от необходимости повторно кодировать его, требуя, чтобы только немного дополнительного кода TLC интегрировало его. Обертки также позволяют объектным модулям или библиотекам использоваться в S-функциях. Это может быть единственным способом развернуть функции, для которых исходный код недоступен, и также позволяет пользователям распределять модели другим, не обнародуя детали реализации, которые могут быть собственными.
Например, вам можно было скомпилировать существующий объектный файл для процессора, на котором не запускается Simulink. Можно записать макет C S-функция и использовать обертку TLC, которая вызывает внешнюю функцию, несмотря на не наличие ее исходного кода. Вы могли столь же функции доступа в библиотеке алгоритмов, оптимизированных для целевого процессора. Выполнение этого требует, чтобы изменения внесения в make-файл шаблона или в противном случае обеспечение средние значения соединились против библиотеки.
Объектные файлы, которые испытывают недостаток в исходном коде и создаются с Microsoft® Visual C и Microsoft Visual C ++® Compiler (MSVC), работают только с MSVC.
Единственное ограничение на обертки S-функции для количества количества соответствия вводов и выводов блока вводов и выводов перенесенной внешней функции. Код обертки может включать вычисления, но обычно они ограничиваются преобразованием значений (например, масштабирование или переформатирование) передал и от перенесенных внешних функций.
В папке в качестве примера “внешняя функция” найдена в файле my_alg.c
. Вам также предоставляют S-функцию C под названием wrapsfcn.c
, который интегрирует my_alg.c
в Simulink. Настройте осуществление можно следующим образом:
Сделайте tlctutorial/wrapper
вашей текущей папкой.
В MATLAB®, открытом модель externalcode
от вашей рабочей папки. Блок-схема выглядит так:
Активируйте блок Scope путем двойного клика по нему.
Запустите модель (из меню Simulation или введите Ctrl+T). Вы получите ошибку при сообщении вам, что wrapsfcn
не существует. Можно ли выяснить почему?
Ошибка происходит, потому что файл mex
не существует для wrapsfcn
. Исправить это, в типе Окна Команды MATLAB
mex wrapsfcn.c
Ошибка может произойти, если вы ранее не запустили mex -setup
.
Запустите симуляцию снова с существующей S-функцией.
Блок s-function умножает свой вход на два. Смотря на блок Scope, вы видите синусоиду, которая колеблется между-2.0 и 2.0. Переменная yout
, которая создается на ваших шагах рабочего пространства MATLAB через эти значения.
В остатке от осуществления вы создаете и запускаете автономную версию модели, затем пишете некоторый код TLC, который позволяет генератору кода создавать независимый исполняемый файл, который вызывает S-функцию my_alg.c
непосредственно.
Прежде, чем создать обертку, сгенерируйте код, который использует Simulink типичный API. Первый шаг должен создать автономную модель.
Выберите Code> C/C++ Code> Build Model.
Генератор кода создает автономную программу в вашей рабочей папке и помещает исходные и объектные файлы в вашу папку сборки. Файл будет назван 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
. Для получения дополнительной информации смотрите Выполнение Внешние Команды, Скрипты и Программы (MATLAB).
Обычно функции, которые будут перенесены, или включены в обертку, как выше, или, когда объектные модули переносятся, разрешаются во время ссылки.
Чтобы создать обертку для внешнего функционального my_alg.c
, необходимо создать файл TLC, который воплощает его функцию вызова, wrapsfcn.c
. Файл TLC должен сгенерировать код С, который обеспечивает:
Прототип функции для внешней функции, которая возвращает двойное, и передает вход double u
.
Вызов функции к my_alg()
в выходном разделе кода.
Чтобы создать обертку для my_alg()
, сделайте следующее:
Откройте файл change_wrapsfcn.tlc
в вашем редакторе и добавьте строки кода, где комментарии указывают, чтобы создать осуществимую обертку.
Сохраните отредактированный файл как wrapsfcn.tlc
. Это должно иметь то же имя как Блок s-function, который использует его, или TLC не называется к встроенному коду.
В MATLAB, открытом модель externalcode
от вашей рабочей папки. Активируйте блок Scope путем двойного клика по нему, и запустите модель (из меню Simulation или введите Ctrl+T). Это дает вам базовый результат.
Сообщите Simulink, что ваш код имеет внешнюю ссылку, которая будет разрешена. Чтобы обновить параметры модели, в Окне Команды MATLAB, выполняют одно из следующих действий:
Ввод
set_param('externalcode/S-Function','SFunctionModules','my_alg')
В диалоговом окне параметров Блока s-function, в поле S-function modules
, задают 'my_alg'
.
Создайте автономное приложение путем ввода одной из следующих команд в Командном окне:
rtwbuild('my_alg','ForceTopModelBuild',true)
slbuild('my_alg', 'StandaloneCoderTarget','ForceTopModelBuild',true)
Эти команды обеспечивают генератор кода, чтобы восстановить топ-модель, которая требуется, когда вы делаете изменения сопоставленными с внешним или пользовательским кодом.
Также можно обеспечить регенерацию кода топ-модели путем удаления папок в папке генерации кода (Simulink), таких как slprj
или сгенерированная папка типового кодекса.
Для получения дополнительной информации смотрите Регенерацию Управления Кода Топ-модели.
Запустите новое автономное приложение и проверьте, что оно приводит к идентичным результатам как в окне scope.
!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
? Вы call my_alg()
с ожидаемым вводом и выводом? Зафиксируйте ошибки и восстановите модель.