wrapper
Обзор руководстваObjective: Узнать архитектуру S-функций оболочки и как создать S-функцию встроенной оболочки с помощью TLC.
<reservedrangesplaceholder1> <reservedrangesplaceholder0>
(открыто)/ toolbox/rtw/rtwdemos/tlctutorial/wrapper
Wrapper S-функции позволяют использовать существующие функции C, не переписывая их полностью в контексте Simulink® S-функции. Каждая оболочка, которую вы предоставляете, является «оболочкой» S-функции, которая просто вызывает одну или несколько существующих внешних функций. Это руководство объясняет и иллюстрирует обертки следующим образом:
Why Wrap User Code? - Причина создания функций обертки TLC
Getting Started - настройте упражнение обертки
Generate Code Without a Wrapper - Как генератор кода обрабатывает внешние функции по умолчанию
Generate Code Using a Wrapper - Обхода накладных расходов API
Многие пользователи Simulink хотят создавать модели, включающие алгоритмы, которые они уже закодировали, реализовали и протестировали в высокоуровневый язык. Обычно такой код вносится в Simulink как S-функции. Чтобы сгенерировать внешнее приложение, интегрирующее пользовательский код, можно принять несколько подходов:
Можно создать S-функцию из пользовательского кода, которая соединяет ее с типовым API Simulink. Это самый простой подход, но жертвует эффективностью для автономных приложений.
Можно встраивать S-функцию, повторно имплементируя ее как файл TLC. Это повышает эффективность, но требует времени и усилий, может ввести ошибки в рабочий код и приводит к двум наборам кода для обслуживания каждого алгоритма, если вы не используете Legacy Code Tool (см. «Импорт вызовов во внешний код» в сгенерированный код с помощью Legacy Code Tool).
Можно встроить S-функцию через TLC- wrapper function. При этом необходимо создать только небольшое количество кода TLC, и алгоритм может остаться закодированным в существующем виде.
Следующий рисунок иллюстрирует, как работают оболочки S-функций.
Перенос функции устраняет необходимость ее перекодирования, требуя для ее интеграции лишь немного дополнительного кода TLC. Оболочки также позволяют использовать объект модули или библиотеки в S-функциях. Это может быть единственным способом развертывания функций, для которых исходный код недоступен, а также позволяет пользователям распространять модели среди других, не разглашая детали реализации, которые могут быть собственными.
Например, у вас может быть существующий файл объекта, скомпилированный для процессора, на котором Simulink не запускается. Можно написать фиктивную S-функцию C и использовать TLC-оболочку, которая вызывает внешнюю функцию, несмотря на отсутствие её исходного кода. Вы можете аналогично получить доступ к функциям в библиотеке алгоритмов, оптимизированной для целевого процессора. Для этого требуется внести изменения в файл make-файла шаблона или иным образом предоставить средство для связи с библиотекой.
Примечание
Файлы объектов, которые не имеют исходного кода и создаются с помощью Microsoft® Visual C и Microsoft Visual C++® Компилятор (MSVC) работает только с MSVC.
Единственное ограничение для оболочек S-функций - это количество входов и выходов блоков, совпадающих с количеством входов и выходов обернутой внешней функции. Код обертки может включать расчеты, но обычно они ограничиваются преобразованием значений (для примера, масштабирования или переформатирования), переданных в и из обернутых внешних функций.
В папке с примером в файле обнаруживается «внешняя функция» my_alg.c
. Вам также предоставляется функция C S, вызываемая 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
непосредственно.
Перед созданием оболочки сгенерируйте код, который использует типовой 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 файла должен сгенерировать Код С, который обеспечивает:
Прототип функции для внешней функции, которая возвращает double и передает входной 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'
.
Создайте автономное приложение путем ввода одной из следующих команд в Командном окне:
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()
с ожидаемыми входом и выходом? Исправьте ошибки и перестроите модель.