Интегрируйте функции C Используя Legacy Code Tool

Обзор

Можно интегрировать существующий C (или C++) функции, такие как драйверы устройств, интерполяционные таблицы, и общие функции и интерфейсы, в модели Simulink® при помощи Legacy Code Tool. Используя спецификации, которые вы предоставляете как код MATLAB®, инструмент преобразовывает существующие функции в S-функции MEX C, которые можно включать в модели Simulink. Если вы используете Simulink Coder™, чтобы сгенерировать код, Legacy Code Tool может вставить соответствующий вызов вашей функции C в сгенерированный код. Для получения дополнительной информации смотрите Вызовы Импорта Внешнего Кода в Сгенерированный код с Legacy Code Tool (Simulink Coder).

По сравнению с использованием Разработчика S-функции или записью S-функции, Legacy Code Tool легче использовать и генерирует оптимизированный код (не генерирует код обертки), часто требуемый встраиваемыми системами. Однако рассмотрите альтернативные подходы для гибридной системы, такие как система, которая включает объект и контроллер или компонент системы, написанный в языке кроме C или C++. Альтернативные подходы более гибки в этом, они поддерживают больше функций и языков программирования.

Взаимодействовать с Legacy Code Tool, вами

  • Используйте структуру данных Legacy Code Tool, чтобы задать

    • Имя для S-функции

    • Спецификации для существующих функций C

    • Файлы и пути требуются для компиляции

    • Опции для сгенерированной S-функции

  • Используйте функцию legacy_code для

    • Инициализируйте структуру данных Legacy Code Tool для данной функции C

    • Сгенерируйте S-функцию для использования во время симуляции

    • Скомпилируйте и соедините сгенерированную S-функцию в динамически загружаемый исполняемый файл

    • Сгенерируйте Блок s-function маскированный для вызова сгенерированной S-функции

    • Сгенерируйте файл блока TLC и, при необходимости, _makecfg.m sFunction или файл rtwmakecfg.m для генерации кода (требуемая лицензия на продукты Simulink Coder)

Примечание

Прежде чем можно будет использовать legacy_code, гарантировать, что компилятор C настраивается для установки MATLAB.

Следующая схема иллюстрирует общую процедуру для использования Legacy Code Tool. Объединяйтесь Функции C в Модели Simulink с Legacy Code Tool обеспечивает пример, который использует Legacy Code Tool, чтобы преобразовать существующую функцию C в S-функцию MEX C.

Если у вас есть лицензия на продукты Simulink Coder, смотрите Вызовы Импорта Внешнего Кода в Сгенерированный код с Legacy Code Tool (Simulink Coder) для получения информации об использовании Legacy Code Tool для генерации кода.

Интегрируйте функции C в модели Simulink с Legacy Code Tool

Этот пример демонстрирует, как интегрировать существующую функцию C в модель Simulink с помощью Legacy Code Tool.

Предположим, что у вас есть функция C, которая выводит значение ее входа с плавающей точкой, умноженного на два. Функция задана в исходном файле под названием doubleIt.c, и его объявление существует в заголовочном файле под названием doubleIt.h.

  1. Инициализируйте struct MATLAB def с полями, которые представляют свойства Legacy Code Tool с помощью функции legacy_code.

    def = legacy_code('initialize')

    Структура данных Legacy Code Tool под названием def отображает свои поля в окне команды MATLAB как показано здесь:

    def = 
    
                  SFunctionName: ''
    InitializeConditionsFcnSpec: ''
                  OutputFcnSpec: ''
                   StartFcnSpec: ''
               TerminateFcnSpec: ''
                    HeaderFiles: {}
                    SourceFiles: {}
                   HostLibFiles: {}
                 TargetLibFiles: {}
                       IncPaths: {}
                       SrcPaths: {}
                       LibPaths: {}
                     SampleTime: 'inherited'
                        Options: [1x1 struct]
  2. Задайте соответствующие значения для полей в структуре данных Legacy Code Tool, чтобы идентифицировать свойства существующей функции C. Например, задайте источник функции C и имена файлов заголовка путем ввода следующих команд в подсказке команды MATLAB:

    def.SourceFiles = {'doubleIt.c'};
    def.HeaderFiles = {'doubleIt.h'};

    Необходимо также указать информацию о S-функции, которую Legacy Code Tool производит из кода С. Например, задайте имя для S-функции и ее объявления выходной функции путем ввода:

    def.SFunctionName = 'ex_sfun_doubleit';
    def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';

    Для получения информации о различных полях структуры данных смотрите страницу с описанием legacy_code.

  3. Сгенерируйте исходный файл S-функции от существующей функции C при помощи функции legacy_code. В подсказке команды MATLAB введите:

    legacy_code('sfcn_cmex_generate', def);

    Legacy Code Tool использует информацию, указанную в def, чтобы создать исходный файл S-функции под названием ex_sfun_doubleit.c в текущей папке MATLAB.

  4. Скомпилируйте и соедините исходный файл S-функции в динамически загружаемый исполняемый файл для Simulink с помощью thelegacy_code функцию. В подсказке команды MATLAB введите:

    legacy_code('compile', def);

    Следующие сообщения появляются в окне команды MATLAB:

    ### Start Compiling ex_sfun_doubleit
        mex('ex_sfun_doubleit.c', 'd:\work\lct_demos\doubleIt.c', 
           '-Id:\work\lct\lct_demos')
    ### Finish Compiling ex_sfun_doubleit
    ### Exit

    В 32-битной системе Microsoft® Windows® получившийся исполняемый файл S-функции называют ex_sfun_doubleit.mexw32.

  5. Вставьте Блок s-function маскированный в модель Simulink.

    legacy_code('slblock_generate', def);

    Legacy Code Tool конфигурирует блок, чтобы использовать S-функцию MEX C, созданную на предыдущем шаге. Кроме того, инструмент маскирует блок, таким образом, что это отображает значение своего свойства OutputFcnSpec (см. описание функции legacy_code).

  6. Добавьте блок Sine Wave амплитуды 1 к входу Блока s-function C-MEX и блока Scope к выводу.

    Запустите симуляцию. Блок s-function C-MEX возвращает значение своего входа с плавающей точкой, умноженного на два. Это ведет себя как функция C doubleIt.

Интегрируйте функцию C, аргументы которой являются указателями на структуры

Этот пример показывает, как использовать Legacy Code Tool, чтобы интегрировать функцию C, аргументы которой являются указателями на структуры.

В Simulink® создайте объект Simulink.Bus представлять тип структуры. Используйте сигналы шины в модели, чтобы представлять структурированные сигналы и состояния. Создайте структуры MATLAB в рабочей области или в диалоговом окне параметров блоков, чтобы представлять структуры параметра.

Для основной информации о сигналах шины смотрите Шины. Для основной информации о структурах параметра смотрите, Организуют Связанные Определения Параметров блоков в Структурах. Чтобы создать объекты шины, смотрите, Создают Объекты Шины с Редактором Шины.

Исследуйте внешний код

Скопируйте этот пользовательский исходный код в файл с именем ex_mySrc_LCT.c в вашей текущей папке.

#include "ex_myTypes_LCT.h"

void myFcn(sigStructType *in, paramStructType *params, sigStructType *out)
{
    out->sig1 = in->sig1 * params->param1;
    out->sig2 = in->sig2 * params->param2 + params->param3;
}

Аргументы функционального myFcn являются указателями на структуры. Функция принимает аргумент входного сигнала, аргумент параметра и аргумент выходного сигнала.

Скопируйте этот пользовательский код заголовка в файл с именем ex_myTypes_LCT.h в вашей текущей папке.

#ifndef _MY_TYPES_H_
#define _MY_TYPES_H_

typedef struct {
  double sig1;
  double sig2;
} sigStructType;

typedef struct {
  double param1;
  double param2;
  double param3;
} paramStructType;

#endif

Файл задает сигнал, и структура параметра вводит тот myFcn использование.

Создайте объекты шины представлять типы структуры в Simulink

В командной строке используйте функциональный Simulink.importExternalCTypes, чтобы сгенерировать объекты шины в базовом рабочем пространстве.

Simulink.importExternalCTypes('ex_myTypes_LCT.h');

Объекты шины соответствуют типам struct, которые задает ex_myTypes_LCT.h.

Создайте блок, чтобы выполнить внешний код

Создайте переменную структуры, def, чтобы сохранить спецификации для S-функции, которая вызывает внешний код. Используйте функциональный legacy_code, чтобы создать структуру и установить значения по умолчанию.

def = legacy_code('initialize');

Определите имя S-функции к sfun_ex_mySrc_LCT.

def.SFunctionName = 'sfun_ex_mySrc_LCT';

Идентифицируйте внешний источник и заголовочные файлы их именами файлов.

def.SourceFiles = {'ex_mySrc_LCT.c'};
def.HeaderFiles = {'ex_myTypes_LCT.h'};

Задайте прототип выходной функции, которая модель вызывает каждый шаг симуляции путем копирования прототипа внешнего функционального myFcn. Определите имена аргументов к u1, p1 и y1, чтобы представлять входной параметр, аргумент параметра и выходной аргумент. Используйте синтаксис [1], чтобы указать, что каждый аргумент является указателем.

def.OutputFcnSpec = ['void myFcn(sigStructType u1[1], ',...
    'paramStructType p1[1], sigStructType y1[1])'];

Используйте функциональный legacy_code, чтобы создать S-функцию и соответствующий исполняемый файл MEX C от спецификации, def. Задайте опцию 'generate_for_sim', чтобы подготовить S-функцию к нормальным и ускоренным симуляциям.

legacy_code('generate_for_sim',def);
### Start Compiling sfun_ex_mySrc_LCT
    mex('-I/tmp/BR2019ad_1035872_198992/publish_examples6/tp753f13fd/ex12763634', '-c', '-outdir', '/tmp/BR2019ad_1035872_198992/publish_examples6/tpcd9fe5a2_97e6_4978_a7cb_ee76833ef802', '/tmp/BR2019ad_1035872_198992/publish_examples6/tp753f13fd/ex12763634/ex_mySrc_LCT.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_ex_mySrc_LCT.c', '-I/tmp/BR2019ad_1035872_198992/publish_examples6/tp753f13fd/ex12763634', '/tmp/BR2019ad_1035872_198992/publish_examples6/tpcd9fe5a2_97e6_4978_a7cb_ee76833ef802/ex_mySrc_LCT.o')
Building with 'gcc'.
/tmp/BR2019ad_1035872_198992/publish_examples6/tp753f13fd/ex12763634/sfun_ex_mySrc_LCT.c: In function ‘mdlOutputs’:
/tmp/BR2019ad_1035872_198992/publish_examples6/tp753f13fd/ex12763634/sfun_ex_mySrc_LCT.c:417:9: warning: implicit declaration of function ‘myFcn’ [-Wimplicit-function-declaration]
         myFcn(__u1BUS, __p1BUS, __y1BUS);
         ^~~~~

MEX completed successfully.
### Finish Compiling sfun_ex_mySrc_LCT
### Exit

Создайте Блок s-function маскированный, который вызывает S-функцию во время симуляции.

legacy_code('slblock_generate', def);

Блок появляется в новой модели.

Чтобы использовать Блок s-function в вашей модели, создайте сигнал шины типа sigStructType, чтобы использовать в качестве входа блока. Блок вывод является также сигналом шины. Маска блока принимает параметр, P1. Чтобы установить значение параметра, используйте структуру MATLAB, поля которой соответствуют, те из структуры вводят paramStructType.

Проверьте подписание внешнего кода

Создайте модель тестовой обвязки, которая проверяет подписание внешнего кода во время симуляции.

Для примера просмотрите модель ex_lct_struct.

open_system('ex_lct_struct')

В диалоговом окне блока Constant параметр Постоянного значения устанавливается на структуру, поля которой соответствуют, те из структуры вводят sigStructType. На вкладке Signal Attributes тип Выходных данных установлен в объект sigStructType шины.

Блок s-function вызывает S-функцию sfun_ex_mySrc_LCT, который вы создали. Вывод блока вводит блок Селектора Шины, который извлекает элементы сигнала sig1 и sig2.

Блок s-function принимает параметр через диалоговое окно маски. Создайте структуру MATLAB structParam, чтобы использовать в качестве значения параметра.

structParam = struct;
structParam.param1 = 15;
structParam.param2 = 20;
structParam.param3 = 5;

Опционально, используйте объект Simulink.Parameter содержать структуру. Если вы используете объект параметра, можно установить тип данных структуры при помощи объекта paramStructType шины.

structParam = Simulink.Parameter(structParam);
structParam.DataType = 'Bus: paramStructType';

В диалоговом окне маски, набор P1 к structParam.

set_param('ex_lct_struct/sfun_ex_mySrc_LCT','SParameter1','structParam')

Моделируйте модель. Блоки Scope показывают, что Блок s-function вызывает внешний функциональный myFcn.

open_system('ex_lct_struct/Scope')
open_system('ex_lct_struct/Scope1')
sim('ex_lct_struct')
ans = 

  Simulink.SimulationOutput:
                   tout: [51x1 double] 

     SimulationMetadata: [1x1 Simulink.SimulationMetadata] 
           ErrorMessage: [0x0 char] 

Регистрация структур данных Legacy Code Tool

Первый шаг к использованию Legacy Code Tool должен указать одну или несколько структур MATLAB с полями, которые представляют свойства существующего кода С и сгенерированной S-функции. Процесс регистрации гибок. Можно принять решение настроить ресурсы и инициировать регистрацию во множестве путей, включая

  • Размещение всего необходимого заголовка и исходных файлов в текущей рабочей папке или в иерархической структуре папок

  • Генерация и размещение одной или нескольких S-функций в текущей рабочей папке

  • Наличие одного или нескольких регистрационных файлов в той же папке

Указывать структуру данных Legacy Code Tool:

  1. Используйте функцию legacy_code, задавая 'initialize' в качестве первого аргумента.

    lct_spec = legacy_code('initialize')

    Структура данных Legacy Code Tool под названием lct_spec отображает свои поля в окне команды MATLAB как показано ниже:

    lct_spec = 
    
                  SFunctionName: ''
    InitializeConditionsFcnSpec: ''
                  OutputFcnSpec: ''
                   StartFcnSpec: ''
               TerminateFcnSpec: ''
                    HeaderFiles: {}
                    SourceFiles: {}
                   HostLibFiles: {}
                 TargetLibFiles: {}
                       IncPaths: {}
                       SrcPaths: {}
                       LibPaths: {}
                     SampleTime: 'inherited'
                        Options: [1x1 struct]
  2. Задайте значения для полей структуры данных (свойства), которые применяются к вашей существующей функции C и S-функции, которую вы намереваетесь сгенерировать. Минимально, необходимо задать

    • Исходные и заголовочные файлы для существующей функции C (SourceFiles и HeaderFiles)

    • Имя для S-функции (SFunctionName)

    • По крайней мере одна функциональная спецификация для S-функции (InitializeConditionsFcnSpec, OutputFcnSpec, StartFcnSpec, TerminateFcnSpec)

    Для полного списка и описаний полей в структуре, смотрите страницу ссылки на функцию legacy_code.

Если вы задаете поля, которые задают ресурсы компиляции, и вы задаете относительные пути, Legacy Code Tool ищет ресурсы относительно следующих директорий в следующем порядке:

  1. Текущая рабочая папка

  2. Папка S-функции C-MEX, если отличающийся, чем текущая рабочая папка

  3. Директории вы задаете

    • IncPaths для заголовочных файлов

    • SrcPaths для исходных файлов

    • LibPaths для цели и библиотек хоста

  4. Директории на пути поиска файлов MATLAB, исключая директории тулбокса

Объявление спецификаций функции Legacy Code Tool

InitializeConditionsFcnSpec, OutputFcnSpec, StartFcnSpec и поля TerminateFcnSpec, заданные в структуре данных Legacy Code Tool (см. описание функции legacy_code), требуют значений вектора символов, которые придерживаются определенного формата синтаксиса. Необходимый формат синтаксиса позволяет Legacy Code Tool сопоставить возвращаемое значение и аргументы существующей функции C к возвращаемому значению, входным параметрам, выходным параметрам, параметрам, и работать векторы S-функции, которую генерирует инструмент.

Общий синтаксис

return-spec = function-name(argument-spec)

Например, следующий вектор символов задает функцию с именем doubleIt со спецификацией возврата double y1 и спецификация входного параметра double u1.

def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';

Для большего количества детали об объявлении функциональных спецификаций смотрите

Возвратите спецификацию

Спецификация возврата задает имя типа данных и имя переменной для возвращаемого значения существующей функции C.

return-type return-variable
return-typeТип данных перечислен в Поддерживаемых Типах данных.
return-variableЛексема формы y1, y2, ..., y n, где n является общим количеством выходных аргументов.

Если функция не возвращает значение, можно не использовать спецификацию возврата или задать его как void.

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

Возвратите типC прототип функцииСпецификация функции Legacy Code Tool
Никакое возвращаемое значениеvoid myfunction(...)void myfunction(...)
Скалярное значениеint = myfunction(...)int16 y1 = myfunction(...)

FunctionName

Имя функции, которое вы задаете, должно совпасть с вашим существующим именем функции C.

Например, рассмотрите следующего прототипа функции C:

float doubleIt(float inVal);

В этом случае именем функции в спецификации функции Legacy Code Tool должен быть doubleIt.

Вы не должны задавать имя макроса C. Если вы должны, установить поле Options.isMacro на true в случае, если сворачивание выражения включено.

Спецификация аргумента

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

argument-type argument-token
argument-typeТип данных перечислен в Поддерживаемых Типах данных.
argument-tokenЛексема одной из следующих форм:
  • Введите — u1, u2, ..., u n, где n является общим количеством входных параметров

  • Вывод y1, y2, ..., y n, где n является общим количеством выходных аргументов

  • Параметр — p1, p2, ..., p n, где n является общим количеством аргументов параметра

  • Векторы работы (постоянная память) — work1, work2, ..., work n, где n является общим количеством аргументов вектора работы

Если функция не имеет никаких аргументов, можно не использовать спецификацию аргумента или задать его как void.

Рассмотрите следующего прототипа функции C:

float powerIt(float inVal, int exponent);

Чтобы сгенерировать S-функцию, которая вызывает предыдущую функцию на каждом временном шаге, устанавливает поле OutputFcnSpec структуры данных Legacy Code Tool на следующее:

'single y1 = powerIt(single u1, int16 p1)'

Используя эту функциональную спецификацию, Legacy Code Tool сопоставляет следующую информацию.

Возвращаемое значение или аргументиз типа CК лексемеиз типа данных
Возвращаемое значениеfloaty1single
inValfloatu1single
exponentintp1int16

Если ваша функция требует Блока s-function Simulink с несколькими портами ввода и вывода, аргументами функции карты к входным портам с помощью исключительно пронумерованной лексемы u. Для выходных портов используйте исключительно пронумерованную лексему y. Эти лексемы описаны в предыдущей таблице спецификации аргумента. Например, рассмотрите следующего прототипа функции C:

void myfunc(double *y2, double u2, double u3, double u1, double *y1);

Вектор символов OutputFcnSpec, сопоставляющий аргументы с портами ввода и вывода, выглядит подобным следующему:

'void myfunc(double y2[1], double u2, double u3, double u1, double y1[1])'

Получившийся Блок s-function включает три входных порта и два выходных порта. Первый вход сопоставляет с аргументом функции u1, второй вход к u2 и третий вход к u3. Для выходных портов аргумент функции, который y1[1] сопоставляет с первым выводом и аргументом y2[1], сопоставляет со вторым выводом. Для другого примера отображения прототипа функции к нескольким портам ввода и вывода смотрите Используя Шины с Устаревшими Функциями, Имеющими Аргументы Структуры.

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

Тип аргументаC прототип функцииСпецификация функции Legacy Code Tool
Входные параметры
Никакие аргументыfunction(void)function(void)
Скалярная передача значениемfunction(int in1)function(int16 u1)
Скалярная передача указателемfunction(int *in1)function(int16 u1[1])
Фиксированный векторfunction(int in1[10]) или
function(int *in1)
function(int16 u1[10])
Переменный векторfunction(int in1[]) или
function(int *in1)
function(int16 u1[])
Фиксированная матрицаfunction(int in1[15]) или
function(int in1[]) или
function(int *in1)
function(int16 u1[3][5])
Переменная матрицаfunction(int in1[]) или
function(int *in1)
function(int16 u1[][])
Выходные аргументы
Скалярный указательfunction(int *y1)function(int16 y1[1])
Фиксированный векторfunction(int y1[10]) или
function(int *y1)
function(int16 y1[10])
Фиксированная матрицаfunction(int y1[15]) или
function(int y1[]) или
function(int *y1)
function(int16 y1[3][5])
Аргументы параметра
Скалярная передача значениемfunction(int p1)function(int16 p1)
Скалярная передача указателемfunction(int *p1)function(int16 p1[1])
Фиксированный векторfunction(int p1[10]) или
function(int *p1)
function(int16 p1[10])
Переменный векторfunction(int p1[]) или
function(int *p1)
function(int16 p1[])
Фиксированная матрицаfunction(int p1[15]) или
function(int p1[]) или
function(int *p1)
function(int16 p1[3][5])
Переменная матрицаfunction(int p1[]) или
function(int *p1)
function(int16 p1[][])
Аргументы вектора работы
Скаляр передается значениемfunction(int work1)function(int16 work1)
Скалярный указательfunction(int *work1)
function(void *work1)
function(void **work1)
function(int16 work1[1])
void function(void *work1)
void function(void **work1)
Фиксированный векторfunction(int work1[10]) или
function(int *work1)
function(int16 work1[10])
Фиксированная матрицаfunction(int work1[15]) или
function(int work1[]) или
function(int *work1)
function(int16 work1[3][5])

Поддерживаемые типы данных

Тип данныхПоддерживаемый для ввода и вывода?Поддерживаемый для параметров?Поддерживаемый для векторов работы?
Типы данных, Поддержанные Simulink (за исключением string)ДаДаДа
Simulink.Bus 1ДаДаДа
Массив Simulink.Bus 2ДаНетДа
Simulink.NumericType 3ДаДаДа
Simulink.AliasType 1ДаДаДа
enum 1ДаДаДа
Фиксированный-point4ДаДаДа
Фи возражаетНет данныхДаНет данных
Комплекс numbers5ДаДаДа
1D массивДаДаДа
2D array6ДаДаДа
n-D array7ДаДаДа
пусто *НетНетДа
пусто **НетНетДа
  1. Необходимо предоставить заголовочный файл, который задает структуру шины, задает тип enum или задает тип данных с тем же именем как псевдоним. Структура шины, объявленной в заголовочном файле, должна совпадать со структурой объекта шины (например, номер и порядок элементов, типов данных и ширин элементов, и так далее). Для примера смотрите sldemo_lct_bus.

    Чтобы сгенерировать объекты типа данных и классы перечисления, которые соответствуют пользовательским типам данных, которые задает ваш код С, используйте функцию Simulink.importExternalCTypes.

  2. Элемент шины может быть комплексным, но только с Simulink встроенные типы данных. Вложение массивов к любому уровню также поддержано.

  3. Необходимо предоставить заголовочный файл, который задает тип данных, только если тип числовых данных является также псевдонимом.

  4. Необходимо объявить данные как объект Simulink.NumericType (незаданное масштабирование не поддержано). Для примеров смотрите sldemo_lct_fixpt_signals и sldemo_lct_fixpt_params.

  5. Ограниченный, чтобы использовать с Simulink встроенные типы данных. Чтобы задать сложный тип данных, заключите встроенный тип данных в угловых скобках (<>) и предварительно ожидайте слово complex (например, complex<double>). Для примера смотрите sldemo_lct_cplxgain.

  6. MATLAB, Simulink и продукты Simulink Coder хранят данные о многомерном массиве в главном столбцом формате как вектор. Если ваш внешний функциональный код записан для главных строкой данных, используйте опцию S-функции convertNDArrayToRowMajor в legacy_code.

  7. Для многомерного сигнала можно использовать функцию size, чтобы определить число элементов в сигнале. Для примеров смотрите sldemo_lct_lut и sldemo_lct_ndarray.

Для получения дополнительной информации смотрите Типы данных, Поддержанные Simulink.

Правила спецификации функции Legacy Code Tool

Спецификации для legacy_code должны придерживаться следующих правил:

  • Если аргумент не является скаляром, необходимо передать аргумент ссылкой.

  • Нумерация входа, вывод, параметр, и работают, лексемы аргумента вектора должны запуститься в 1 и увеличиться монотонно.

  • Для данной структуры данных Legacy Code Tool, типа данных и размера входа, вывода, параметра, и работают, аргументы вектора должны быть тем же самым через функциональные спецификации для StartFcnSpec, InitializeConditionsFcnSpec, OutputFcnSpec и TerminateFcnSpec.

  • Можно задать размерности аргумента с выражениями, которые используют следующее:

    • Функции: numel, size

    • Значения параметров

    • Операторы: +, -, * и /

    • Целочисленные и литералы с плавающей точкой

    • Круглые скобки для группировки подвыражений

    Например:

    def.OutputFcnSpec=
    foo4(int8 p1[], int8 u1[], double y1[numel(u1)+2][numel(u1)+3], ...
    int32 (numel(p1)+numel(u1))*2+size(y1,2))';

Наследие C функциональные правила

Чтобы интегрировать функцию C использование Legacy Code Tool, функция должна придерживаться следующих правил:

  • Функция не должна изменять значение входных параметров. Если входной сигнал является переданным ссылкой аргументом к функции, функция не должна изменять данные, на которые указывает аргумент.

  • Возвращаемое значение функции не может быть указателем.

  • Функциональные спецификации, которые вы задаете для StartFcnSpec, InitializeConditionsFcnSpec или TerminateFcnSpec, не могут получить доступ к аргументам ввода или вывода. Для StartFcnSpec и InitializeConditionsFcnSpec, можно получить доступ к выходным портам, если опция S-функции outputsConditionallyWritten установлена в true. С этой установкой опции сгенерированная S-функция указывает, что память, сопоставленная с каждым выходным портом, не может быть перезаписана и глобальна (SS_NOT_REUSABLE_AND_GLOBAL).

Генерация и компиляция S-функций

После того, как вы укажете структуру данных Legacy Code Tool для существующей функции C, используйте функцию legacy_code, как объяснено ниже, чтобы сгенерировать, скомпилировать, и соединить S-функцию.

  1. Сгенерируйте S-функцию MEX C на основе информации, заданной в структуре. Вызовите legacy_code с 'sfcn_cmex_generate' в качестве первого аргумента и имени структуры данных в качестве второго аргумента.

    legacy_code('sfcn_cmex_generate', lct_spec);
  2. Скомпилируйте и соедините S-функцию. Этот шаг принимает, что компилятор C настраивается для вашей установки MATLAB. Вызовите legacy_code с 'compile' в качестве первого аргумента и имени структуры данных в качестве второго аргумента.

    legacy_code('compile', lct_spec);
    

    Информационные сообщения, подобные следующему, появляются в окне команды MATLAB, и заканчивается динамически загружаемый исполняемый файл. В 32-битной системе Windows, названия программного обеспечения Simulink файл ex_sfun_doubleit.mexw32.

    ### Start Compiling ex_sfun_doubleit
    mex  ex_sfun_doubleit.c -Id:\work\lct\lct_demos
    ### Finish Compiling ex_sfun_doubleit
    ### Exit

Как удобство, можно сгенерировать, скомпилировать и соединить S-функцию на одном шаге путем вызова legacy_code с вектором символов 'generate_for_sim'. Функция также генерирует файл TLC для ускоренных симуляций, если поле Options.useTlcWithAccel структуры данных Legacy Code Tool установлено в 1.

Если вы сгенерировали динамически загружаемый исполняемый файл, вы или другие можете использовать его в модели путем добавления Блока s-function, который задает скомпилированную S-функцию.

Генерация блока s-function маскированного для вызова сгенерированной S-функции

У вас есть опция использования Legacy Code Tool, чтобы сгенерировать Блок s-function маскированный (графическое представление), которое сконфигурировано, чтобы вызвать сгенерированную S-функцию MEX C. Чтобы сгенерировать такой блок, вызовите legacy_code с 'slblock_generate' в качестве первого аргумента и имени структуры данных Legacy Code Tool в качестве второго аргумента.

legacy_code('slblock_generate', lct_spec);

Инструмент маскирует блок, таким образом, что это отображает значение поля OutputFcnSpec. Можно затем добавить блок в модель вручную.

Если вы предпочитаете, чтобы Legacy Code Tool добавил блок в модель автоматически, задал имя модели в качестве третьего аргумента. Например:

legacy_code('slblock_generate', lct_spec, 'myModel');

Если заданная модель (например, myModel) существует, legacy_code открывает модель и добавляет Блок s-function маскированный, описанный структурой данных Legacy Code Tool. Если модель не существует, функция создает новую модель с указанным именем и добавляет Блок s-function маскированный.

Принуждение режима Accelerator Simulink, чтобы использовать S-функцию TLC, встраивающую код

Если вы используете режим Simulink Accelerator™, можно сгенерировать и обеспечить использование TLC встраивание кода для S-функции, сгенерированной Legacy Code Tool. Для этого:

  1. Сгенерируйте файл блока TLC для S-функции путем вызывания функции legacy_code с 'sfcn_tlc_generate' в качестве первого аргумента и имени структуры данных Legacy Code Tool в качестве второго аргумента.

    legacy_code('sfcn_tlc_generate', lct_spec);

    Полагайте, что пример в Интегрирует Функции C в Модели Simulink с Legacy Code Tool. Чтобы сгенерировать файл TLC для модели, показанной в конце того примера, введите следующую команду:

    legacy_code('sfcn_tlc_generate', def);
  2. Обеспечьте Режим Accelerator, чтобы использовать файл TLC при помощи функции SimStruct ssSetOptions, чтобы установить опцию S-функции SS_OPTION_USE_TLC_WITH_ACCELERATOR.

Вызывание наследия функции C++

Чтобы вызвать устаревшую функцию C++ после инициализации структуры данных Legacy Code Tool, присвойте значение 'C++' полю Options.language. Например,

def = legacy_code('initialize');
def.Options.language = 'C++';

Чтобы проверить новую установку, войти

def.Options.language

Примечание

Legacy Code Tool может взаимодействовать через интерфейс с функциями C++, но не объектами C++. Для работы вокруг, смотрите Ограничения Legacy Code Tool в документации Simulink.

Обработка нескольких регистрационных файлов

Вы можете иметь несколько регистрационных файлов в той же папке и сгенерировать S-функцию для каждого файла с одним вызовом legacy_code. Аналогично, можно использовать один вызов legacy_code в порядке скомпилировать и соединить S-функции и другого, чтобы сгенерировать соответствующие файлы блока TLC, в подходящих случаях.

Рассмотрите следующий пример, где lct_register_1, lct_register_2 и lct_register_3 каждый создает и инициализирует поля структуры Legacy Code Tool.

defs1 = lct_register_1;
defs2 = lct_register_2;
defs3 = lct_register_3;
defs = [defs1(:);defs2(:);defs3(:)];

Можно затем использовать следующую последовательность вызовов legacy_code в порядке сгенерировать файлы на основе трех регистрационных файлов:

legacy_code('sfcn_cmex_generate', defs);
legacy_code('compile', defs);
legacy_code('sfcn_tlc_generate', defs);

Также можно обработать каждый регистрационный файл отдельно. Например:

defs1 = lct_register1;
legacy_code('sfcn_cmex_generate', defs1);
legacy_code('compile', defs1);
legacy_code('sfcn_tlc_generate', defs1);
.
.
.
defs2 = lct_register2;
legacy_code('sfcn_cmex_generate', defs2);
legacy_code('compile', defs2);
legacy_code('sfcn_tlc_generate', defs2);
.
.
.
defs3 = lct_register3;
legacy_code('sfcn_cmex_generate', defs3);
legacy_code('compile', defs3);
legacy_code('sfcn_tlc_generate', defs3);

Развертывание сгенерированных S-функций

Можно развернуть S-функции, которые вы генерируете с Legacy Code Tool для использования другими. Чтобы развернуть S-функцию для симуляции используют только, необходимо совместно использовать только скомпилированный динамически загружаемый исполняемый файл.

Примеры Legacy Code Tool

Чтобы видеть примеры Legacy Code Tool, в окне команды MATLAB, введите:

Примеры Legacy Code Tool перечислены в Моделировании Функций> Авторские блоки с S-функциями, Системными объектами и Legacy Code Tool.

Ограничения Legacy Code Tool

Legacy Code Tool

  • Генерирует S-функции MEX C для существующих функций, написанных в C или C++. Инструмент не поддерживает преобразование функций MATLAB или Фортрана.

  • Может взаимодействовать через интерфейс с функциями C++, но не объектами C++. Один способ работать вокруг этого ограничения состоит в том, чтобы использовать Разработчика S-функции, чтобы сгенерировать интерпретатор S-функции и затем вызвать устаревший Код С++ от функции обратного вызова mdlOutputs S-функции.

  • Не поддерживает моделирующие непрерывные или дискретные состояния. Это препятствует тому, чтобы вы использовали функции обратного вызова mdlDerivatives и mdlUpdate. Если ваше приложение требует этой поддержки, смотрите Используя Разработчика S-функции, чтобы Включить Унаследованный код.

  • Всегда устанавливает флаг S-функций для прямого сквозного соединения (sizes.DirFeedthrough) к true. Из-за этой установки и предыдущего ограничения, сгенерированная S-функция не может повредить алгебраические циклы.

  • Поддержки только непрерывное, но зафиксированный в незначительном временном шаге, шаге расчета и опции смещения.

  • Комплексные числа поддержек, но только с Simulink встроенные типы данных.

  • Не поддерживает использование указателей функции как вывод устаревшей вызванной функции.

  • Не поддерживает следующие функции S-функции:

    • Векторы работы, кроме векторов генерала Дуорка

    • Основанные на кадре сигналы ввода и вывода

    • Основанные на порте шаги расчета

    • Несколько основанных на блоке шагов расчета

  • Не поддерживает использование осциллографа (: :) оператор для доступа данных о классе C++ и методов. Для статических методов можно записать простые макросы препроцессора, подобные следующему, чтобы работать вокруг этого:

    #define CCommon_computeVectorDotProduct CCommon::computeVectorDotProduct

Для просмотра документации необходимо авторизоваться на сайте