Перенесите пользовательский код с TLC

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. Настройте осуществление можно следующим образом:

  1. Сделайте tlctutorial/wrapper ваша текущая папка.

  2. В MATLAB®, открытом модель externalcode от вашей рабочей папки. Блок-схема выглядит так:

  3. Активируйте блок Scope путем двойного клика по нему.

  4. Запустите модель (от вкладки Simulation или введите Ctrl+T). Вы получите ошибку при сообщении вам того wrapsfcn не существует. Можно ли выяснить почему?

  5. Ошибка происходит потому что mex файл не существует для wrapsfcn. Исправить это, в типе командного окна MATLAB

    mex wrapsfcn.c

    Примечание

    Ошибка может произойти, если вы ранее не запустили mex -setup.

  6. Запустите симуляцию снова с существующей S-функцией.

Блок S-Function умножает свой вход на два. Смотря на блок Scope, вы видите синусоиду, которая колеблется между-2.0 и 2.0. Переменная yout это создается на ваших шагах рабочего пространства MATLAB через эти значения.

В остатке от осуществления вы создаете и запускаете автономную версию модели, затем пишете некоторый код TLC, который позволяет генератору кода создавать независимый исполняемый файл, который вызывает S-функцию my_alg.c непосредственно.

Сгенерируйте код без обертки

Прежде, чем создать обертку, сгенерируйте код, который использует Simulink типовой API. Первый шаг должен создать автономную модель.

  1. На вкладке C Code нажмите Build.

    Генератор кода создает автономную программу в вашей рабочей папке и помещает исходные и объектные файлы в вашу папку сборки. Файл будет назван externalcode.exe на платформах Microsoft Windows® или externalcode на платформах UNIX®.

    Когда это генерирует программу, генератор кода сообщает о своем прогрессе командного окна MATLAB. Итоговые линии:

    ### Created executable: externalcode.exe  
    ### Successful completion of build procedure 
    for model: externalcode
  2. Запустите автономную программу, чтобы видеть, что она ведет себя то же самое как версия Simulink. Не должно быть различий.

    !externalcode
     
    ** starting the model ** 
    ** created externalcode.mat ** 
  3. Заметьте эту линию в 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 u.

  • Вызов функции к my_alg() в выходном разделе кода.

Создать обертку для my_alg(), сделайте следующее:

  1. Откройте файл change_wrapsfcn.tlc в вашем редакторе, и добавляют строки кода, где комментарии указывают, чтобы создать осуществимую обертку.

  2. Сохраните отредактированный файл как wrapsfcn.tlc. Это должно иметь то же имя как блок S-function, который использует его, или TLC не называется к встроенному коду.

  3. В MATLAB, открытом модель externalcode от вашей рабочей папки. Активируйте блок Scope путем двойного клика по нему, и запустите модель (от вкладки Simulation или введите Ctrl+T). Это дает вам базовый результат.

  4. Сообщите Simulink, что ваш код имеет внешнюю ссылку, которая будет разрешена. Чтобы обновить параметры модели, в командном окне MATLAB, выполняют одно из следующих действий:

    • Ввод

      set_param('externalcode/S-Function','SFunctionModules','my_alg')

    • В диалоговом окне параметров блоков S-Function, в S-function modules поле, задайте 'my_alg'.

  5. Создайте автономное приложение путем ввода одной из следующих команд в Командном окне:

    rtwbuild('my_alg','ForceTopModelBuild',true)
    slbuild('my_alg', 'StandaloneCoderTarget','ForceTopModelBuild',true)

    Эти команды обеспечивают генератор кода, чтобы восстановить топ-модель, которая требуется, когда вы делаете изменения сопоставленными с внешним или пользовательским кодом.

    В качестве альтернативы можно обеспечить регенерацию кода топ-модели путем удаления папок в папке генерации кода, таких как slprj или сгенерированная папка типового кодекса.

    Для получения дополнительной информации смотрите Регенерацию Управления Кода Топ-модели.

  6. Запустите новое автономное приложение и проверьте, что оно приводит к идентичным результатам как в окне 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() с ожидаемым вводом и выводом? Зафиксируйте ошибки и восстановите модель.

Похожие темы