Существующие функции C (или C++), такие как драйверы устройств, таблицы поиска и общие функции и интерфейсы, можно интегрировать в модели Simulink ® с помощью инструмента Legacy Code Tool. Используя спецификации, поставляемые в виде кода MATLAB ®, инструмент преобразует существующие функции в S-функции C MEX, которые можно включить в модели Simulink. Если для создания кода используется Simulink Coder™, инструмент Legacy Code Tool может вставить соответствующий вызов функции C в созданный код. Дополнительные сведения см. в разделе Импорт вызовов внешнего кода в сгенерированный код с помощью инструмента кода прежней версии (Simulink Coder).
По сравнению с использованием S-Function Builder или написанием S-функции, Legacy Code Tool проще в использовании и генерирует оптимизированный код (не генерирует код оболочки), часто требуемый встроенными системами. Однако рассмотрим альтернативные подходы для гибридной системы, такой как система, которая включает в себя установку и контроллер, или компонент системы, написанный на языке, отличном от C или C++. Альтернативные подходы более гибки в том смысле, что они поддерживают больше функций и языков программирования.
Для взаимодействия с инструментом устаревшего кода
Использование устаревшей структуры данных инструмента кода для определения
Имя S-функции
Спецификации для существующих функций C
Файлы и пути, необходимые для компиляции
Опции для сгенерированной S-функции
Используйте legacy_code функция для
Инициализация структуры данных Legacy Code Tool для данной функции C
Создание S-функции для использования во время моделирования
Компиляция и связывание созданной S-функции с динамически загружаемым исполняемым файлом
Создание маскированного блока S-функции для вызова сгенерированной S-функции
Создание файла блока TLC и, при необходимости, sFunction_makecfg.m или rtwmakecfg.m файл для генерации кода (требуется лицензия на продукт Simulink Coder)
Примечание
Перед использованием legacy_codeубедитесь, что для установки MATLAB настроен компилятор C.
На следующей схеме показана общая процедура использования инструмента «Устаревший код» (Legacy Code Tool). Интеграция функций C в модели Simulink с помощью инструмента Legacy Code Tool предоставляет пример, который использует инструмент Legacy Code Tool для преобразования существующей функции C в S-функцию C MEX.

Если у вас есть лицензия на продукт Simulink Coder, см. раздел Импорт вызовов внешнего кода в сгенерированный код с помощью прежнего инструмента Code Tool (Simulink Coder Tool) для получения информации об использовании прежнего инструмента Code Tool для создания кода.
В этом примере показано, как интегрировать существующую функцию C в модель Simulink с помощью инструмента Legacy Code Tool.
Предположим, что у вас есть функция C, которая выводит значение ее ввода с плавающей запятой, умноженное на два. Функция определена в исходном файле с именем doubleIt.c, и его объявление существует в файле заголовка с именем doubleIt.h.

Инициализация структуры MATLAB def с полями, представляющими свойства устаревшего инструмента кода с помощью legacy_code функция.
def = legacy_code('initialize')Структура данных прежнего инструмента кода с именем def отображает поля в окне команды MATLAB, как показано ниже:
def =
SFunctionName: ''
InitializeConditionsFcnSpec: ''
OutputFcnSpec: ''
StartFcnSpec: ''
TerminateFcnSpec: ''
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: 'inherited'
Options: [1x1 struct]Укажите соответствующие значения для полей в структуре данных прежнего инструмента кода, чтобы определить свойства существующей функции C. Например, укажите исходные и заголовочные имена функций C, введя в командной строке MATLAB следующие команды:
def.SourceFiles = {'doubleIt.c'};
def.HeaderFiles = {'doubleIt.h'};Кроме того, необходимо указать информацию о S-функции, создаваемую инструментом устаревшего кода из кода C. Например, укажите имя S-функции и ее объявление выходной функции, введя:
def.SFunctionName = 'ex_sfun_doubleit'; def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';
Для получения информации о различных полях структуры данных см. legacy_code справочная страница.
Создайте исходный файл S-функции из существующей C-функции с помощью legacy_code функция. В командной строке MATLAB введите:
legacy_code('sfcn_cmex_generate', def);Инструмент устаревшего кода использует информацию, указанную в def для создания исходного файла S-функции с именем ex_sfun_doubleit.c в текущей папке MATLAB.
Скомпилировать и связать исходный файл S-функции в динамически загружаемый исполняемый файл для Simulink с помощьюlegacy_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.
Вставка маскированного S-функционального блока в модель Simulink.
legacy_code('slblock_generate', def);Legacy Code Tool настраивает блок для использования S-функции C MEX, созданной на предыдущем шаге. Кроме того, инструмент маскирует блок так, чтобы он отображал значение своего OutputFcnSpec (см. описание legacy_code функция).
Добавьте синусоидальный блок амплитуды 1 на вход S-функционального блока C-MEX и блок Scope на выход.

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

В этом примере показано, как использовать устаревший инструмент кода для интеграции функции C, аргументы которой указывают на структуры.
В Simulink ® создайте Simulink.Bus объект для представления типа структуры. Сигналы шины используются в модели для представления структурированных сигналов и состояний. Создайте структуры MATLAB в рабочем пространстве или в диалоговом окне параметров блока для представления структур параметров.
Основные сведения о сигналах шины см. в разделе Виртуальная шина. Основные сведения о структурах параметров см. в разделе Организация определений связанных параметров блоков в структурах. Сведения о создании объектов шины см. в разделе Создание и указание объектов Simulink.Bus.
Изучение внешнего кода
Скопировать этот пользовательский исходный код в файл с именем 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;
void myFcn(sigStructType *in, paramStructType *params, sigStructType *out);
#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-функции и соответствующего исполняемого файла C MEX из спецификации, def. Укажите опцию 'generate_for_sim' для подготовки S-функции к нормальному и ускоренному моделированию.
legacy_code('generate_for_sim',def);
### Start Compiling sfun_ex_mySrc_LCT
mex('-I/tmp/BR2021ad_1584584_202060/publish_examples13/tp1adb5b81/ex12763634', '-c', '-outdir', '/tmp/BR2021ad_1584584_202060/publish_examples13/tp6c5c5b35_65b0_40a1_bf2b_a8cd7d349cb4', '/tmp/BR2021ad_1584584_202060/publish_examples13/tp1adb5b81/ex12763634/ex_mySrc_LCT.c')
Building with 'gcc'.
MEX completed successfully.
mex('sfun_ex_mySrc_LCT.c', '-I/tmp/BR2021ad_1584584_202060/publish_examples13/tp1adb5b81/ex12763634', '/tmp/BR2021ad_1584584_202060/publish_examples13/tp6c5c5b35_65b0_40a1_bf2b_a8cd7d349cb4/ex_mySrc_LCT.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_ex_mySrc_LCT
### Exit
Создайте маскированный блок S-функции, который вызывает S-функцию во время моделирования.
legacy_code('slblock_generate', def);

Блок появится в новой модели.
Для использования блока S-Function в модели создайте сигнал шины типа sigStructType для использования в качестве блочного ввода. Блочный выход также является сигналом шины. Маска блока принимает параметр P1. Для установки значения параметра используйте структуру MATLAB, поля которой соответствуют полям типа структуры. paramStructType.
Проверка выполнения внешнего кода
Создайте модель кабельных трасс, которая проверяет выполнение внешнего кода во время моделирования.
Пример: просмотр модели ex_lct_struct.
open_system('ex_lct_struct')

В диалоговом окне «Блок константы» параметру «Значение константы» присваивается значение структуры, поля которой соответствуют полям типа структуры. sigStructType. На вкладке Signal Attributes тип данных Output устанавливается в объект шины. 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') %


Первым шагом к использованию инструмента кода Legacy Code Tool является регистрация одной или нескольких структур MATLAB с полями, которые представляют свойства существующего кода C и генерируемой S-функции. Процесс регистрации является гибким. Вы можете настроить ресурсы и инициировать регистрацию различными способами, в том числе
Размещение всех требуемых заголовочных и исходных файлов в текущей рабочей папке или в иерархической структуре папок
Создание и размещение одной или нескольких S-функций в текущей рабочей папке
Наличие одного или нескольких файлов регистрации в одной папке
Чтобы зарегистрировать старую структуру данных инструмента кода, выполните следующие действия.
Используйте legacy_code функция, указание 'initialize' в качестве первого аргумента.
lct_spec = legacy_code('initialize')Структура данных прежнего инструмента кода с именем lct_spec отображает поля в окне команды MATLAB, как показано ниже:
lct_spec =
SFunctionName: ''
InitializeConditionsFcnSpec: ''
OutputFcnSpec: ''
StartFcnSpec: ''
TerminateFcnSpec: ''
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: 'inherited'
Options: [1x1 struct]Определите значения для полей структуры данных (свойств), которые применяются к существующей функции C и S-функции, которую требуется создать. Минимально необходимо указать
Исходные и заголовочные файлы для существующей функции C (SourceFiles и HeaderFiles)
Имя S-функции (SFunctionName)
По крайней мере, одна спецификация функции для S-функции (InitializeConditionsFcnSpec, OutputFcnSpec, StartFcnSpec, TerminateFcnSpec)
Полный список и описания полей в структуре см. в разделе legacy_code страница ссылки на функцию.
Если определены поля, определяющие ресурсы компиляции, и указаны относительные пути, инструмент «Код из прежних версий» выполняет поиск ресурсов относительно следующих каталогов в следующем порядке:
Текущая рабочая папка
Папка C-MEX S-function, если она отличается от текущей рабочей папки
Указанные каталоги
IncPaths для заголовочных файлов
SrcPaths для исходных файлов
LibPaths для целевых и хост-библиотек
Каталоги на пути поиска MATLAB, исключая каталоги панели инструментов
InitializeConditionsFcnSpec, OutputFcnSpec, StartFcnSpec, и TerminateFcnSpec
поля, определенные в структуре данных инструмента Legacy Code (см. описание legacy_code функция) требуют значений символьных векторов, которые соответствуют определенному синтаксическому формату. Требуемый формат синтаксиса позволяет инструменту устаревшего кода сопоставлять возвращаемое значение и аргументы существующей функции 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
| Тип данных, указанный в разделе Поддерживаемые типы данных. |
| Маркер формы y1, y2, ..., yn, где n - общее число выходных аргументов. |
Если функция не возвращает значение, можно опустить спецификацию возврата или указать ее как void.
В следующей таблице показан допустимый синтаксис спецификации функции для целочисленного возвращаемого значения. Используйте таблицу для определения синтаксиса, который следует использовать для прототипа функции C.
| Тип возврата | Прототип функции C | Спецификация функции устаревшего инструмента кода |
|---|---|---|
| Нет возвращаемого значения | void myfunction(...) | void myfunction(...) |
| Скалярное значение | int = myfunction(...) | int16 y1 = myfunction(...) |
Указанное имя функции должно совпадать с именем существующей функции C.
Например, рассмотрим следующий прототип функции C:
float doubleIt(float inVal);
В этом случае имя функции в спецификации функции Legacy Code Tool должно быть doubleIt.
Не следует указывать имя макроса C. При необходимости установите поле Options.isMacro кому true в случае включения сворачивания выражения.
Спецификация аргумента определяет один или несколько типов данных и пар маркеров, которые представляют входные, выходные, параметры и аргументы рабочего вектора существующей функции C. Входные и выходные аргументы функции сопоставляются с входными и выходными портами блока, а параметры сопоставляются с параметрами рабочей области.
argument-type argument-token
| Тип данных, указанный в разделе Поддерживаемые типы данных. |
| Маркер одной из следующих форм:
|
Если функция не имеет аргументов, можно опустить спецификацию аргументов или указать ее как void.
Рассмотрим следующий прототип функции C:
float powerIt(float inVal, int exponent);
Чтобы создать S-функцию, которая вызывает предыдущую функцию на каждом шаге времени, установите поле структуры данных Legacy Code Tool OutputFcnSpec к следующему:
'single y1 = powerIt(single u1, int16 p1)'
Используя эту спецификацию функции, инструмент «Унаследованный код» сопоставляет следующую информацию.
| Возвращаемое значение или аргумент | типа C | К символу | типа данных |
|---|---|---|---|
| Возвращаемое значение | float | y1 | single |
inVal | float | u1 | single |
exponent | int | p1 | int16 |
Если для вашей функции требуется S-функциональный блок 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-функциональный блок включает в себя три входных порта и два выходных порта. Первый входной аргумент соответствует аргументу функции u1, второй вход в u2и третий вход в u3. Для выходных портов аргумент function y1[1] сопоставляется с первым выводом и аргументом y2[1] сопоставляется со вторым выводом. Другой пример сопоставления прототипа функции с несколькими портами ввода и вывода см. в разделе Использование шин с устаревшими функциями, имеющими аргументы структуры.
В следующей таблице показан допустимый синтаксис спецификации функции для аргументов типа integer. Используйте таблицу, чтобы определить, а затем адаптировать синтаксис, который следует использовать для прототипа функции C.
| Тип аргумента | Прототип функции C | Спецификация функции устаревшего инструмента кода |
|---|---|---|
| Входные аргументы | ||
| Нет аргументов | 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.Bus1 | Да | Да | Да |
Массив Simulink.Bus2 | Да | Нет | Да |
Simulink.NumericType3 | Да | Да | Да |
Simulink.AliasType1 | Да | Да | Да |
enum1 | Да | Да | Да |
| Fixed-point4 | Да | Да | Да |
| Объекты Fi | Н/Д | Да | Н/Д |
| Комплексные нумерации5 | Да | Да | Да |
| 1-D массив | Да | Да | Да |
| 2-D массив 6 | Да | Да | Да |
| массив n-D 7 | Да | Да | Да |
| void * | Нет | Нет | Да |
| void * * | Нет | Нет | Да |
Необходимо предоставить файл заголовка, который определяет структуру шины, определяет enum или определяет тип данных с тем же именем, что и псевдоним. Структура шины, объявленной в файле заголовка, должна соответствовать структуре объекта шины (например, количество и порядок элементов, типы данных и ширина элементов и так далее). Пример см. в разделе Использование шин с унаследованными функциями, имеющими аргументы структуры.
Для создания объектов типов данных и классов перечисления, соответствующих пользовательским типам данных, определяемым кодом C, используйте Simulink.importExternalCTypes функция.
Элемент шины может быть сложным, но только со встроенными типами данных Simulink. Также поддерживается вложение массивов в любой уровень.
Необходимо указать файл заголовка, определяющий тип данных, только если числовой тип данных также является псевдонимом.
Необходимо объявить данные как Simulink.NumericType (неуказанное масштабирование не поддерживается). Примеры см. в разделах Сигналы фиксированных точек в унаследованных функциях и Параметры фиксированных точек в унаследованных функциях.
Возможность использования только со встроенными типами данных Simulink. Чтобы указать сложный тип данных, заключите встроенный тип данных в угловые скобки (< >) и добавьте словоcomplex (например, complex<double>). Пример см. в разделе Сложные сигналы в прежней функции.
Продукты MATLAB, Simulink и Simulink Coder хранят многомерные данные массива в формате больших столбцов в виде вектора. Если внешний код функции записан для основных данных строки, используйте convertNDArrayToRowMajor Опция S-функции в legacy_code.
Для многомерного сигнала можно использовать size определение количества элементов в сигнале. Примеры см. в разделе Таблицы поиска, реализованные в унаследованных функциях, и многомерные сигналы в унаследованных функциях.
Дополнительные сведения см. в разделе Типы данных, поддерживаемые Simulink.
Спецификации для 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 с помощью прежнего инструмента кода эта функция должна соответствовать следующим правилам:
Функция не должна изменять значение входных аргументов. Если входной сигнал является аргументом, передаваемым по ссылке функции, функция не должна изменять данные, на которые указывает аргумент.
Возвращаемое значение функции не может быть указателем.
Спецификации функций, определяемые для StartFcnSpec, InitializeConditionsFcnSpec, или TerminateFcnSpec не удается получить доступ к входным или выходным аргументам. Для StartFcnSpec и InitializeConditionsFcnSpec, вы можете получить доступ к портам вывода, если опция S-Function outputsConditionallyWritten имеет значение true. При этом параметре генерируемая S-функция указывает, что память, связанная с каждым портом вывода, не может быть перезаписана и является глобальной (SS_NOT_REUSABLE_AND_GLOBAL).
После регистрации устаревшей структуры данных инструмента кода для существующей функции C используйте legacy_code как описано ниже, для генерации, компиляции и связывания S-функции.
Создайте S-функцию C MEX на основе информации, определенной в структуре. Звонить legacy_code с 'sfcn_cmex_generate' в качестве первого аргумента и имя структуры данных в качестве второго аргумента.
legacy_code('sfcn_cmex_generate', lct_spec);Скомпилировать и связать S-функцию. На этом шаге предполагается, что для установки 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-функционального блока (графического представления), сконфигурированного для вызова сгенерированной C MEX S-функции, можно использовать инструмент устаревшего кода. Чтобы создать такой блок, вызовите legacy_code с 'slblock_generate' в качестве первого аргумента и имя структуры данных Legacy Code Tool в качестве второго аргумента.
legacy_code('slblock_generate', lct_spec);
Инструмент маскирует блок так, чтобы он отображал значение OutputFcnSpec поле. Затем блок можно добавить в модель вручную.
При необходимости автоматического добавления блока в модель в качестве третьего аргумента укажите имя модели. Например:
legacy_code('slblock_generate', lct_spec, 'myModel');
Если указанная модель (например, myModel) существует, legacy_code открывает модель и добавляет маскированный блок S-функции, описанный в структуре данных Legacy Code Tool. Если модель не существует, функция создает новую модель с указанным именем и добавляет маскированный блок S-функции.
Если используется режим Simulink Accelerator™, можно создать и принудительно использовать TLC inlining code для S-функции, созданной с помощью инструмента Legacy Code Tool. Для этого:
Создайте файл блока TLC для S-функции путем вызова legacy_code функция с 'sfcn_tlc_generate' в качестве первого аргумента и имя структуры данных Legacy Code Tool в качестве второго аргумента.
legacy_code('sfcn_tlc_generate', lct_spec);Рассмотрим пример в разделе Интеграция функций C в модели Simulink с устаревшим инструментом кода. Чтобы создать файл TLC для модели, показанной в конце этого примера, введите следующую команду:
legacy_code('sfcn_tlc_generate', def);Принудительный режим ускорителя для использования файла TLC с помощью ssSetOptions
SimStruct для установки опции S-функции SS_OPTION_USE_TLC_WITH_ACCELERATOR.
Чтобы вызвать унаследованную функцию C++ после инициализации структуры данных инструмента Legacy Code Tool, присвойте значение «C++» Options.language поле. Например,
def = legacy_code('initialize');
def.Options.language = 'C++';Для проверки новой настройки введите
def.Options.language
Примечание
Legacy Code Tool может взаимодействовать с функциями C++, но не с объектами C++. Описание обхода см. в разделе Ограничения устаревших инструментов кода в документации Simulink.
Вы можете иметь несколько файлов регистрации в одной папке и создать S-функцию для каждого файла с одним вызовом legacy_code. Аналогично, можно использовать один вызов для legacy_code для того, чтобы скомпилировать и связать S-функции и другую для генерации соответствующих файлов блоков TLC, если это уместно.
Рассмотрим следующий пример, где lct_register_1, lct_register_2, и lct_register_3 каждый создает и инициализирует поля устаревшей структуры инструмента кода.
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-функцию только для моделирования, необходимо предоставить общий доступ только к динамически загружаемому исполняемому файлу.
Примеры инструмента «Устаревший код» см. в разделе Реализация алгоритмов с помощью инструмента «Устаревший код».
Устаревший инструмент кода
Генерирует S-функции C MEX для существующих функций, написанных на C или C++. Инструмент не поддерживает преобразование функций MATLAB или Fortran.
Может взаимодействовать с функциями C++, но не с объектами C++. Одним из способов обхода этого ограничения является использование S-Function Builder для создания оболочки S-функции, а затем вызов унаследованного кода C++ из S-функции. mdlOutputs функция обратного вызова.
Не поддерживает моделирование непрерывных или дискретных состояний. Это предотвращает использование mdlUpdate и mdlDerivatives функции обратного вызова. Если приложению требуется эта поддержка, см. раздел Использование S-Function Builder для включения устаревшего кода.
Всегда устанавливает флаг S-функций для прямого прохождения (sizes.DirFeedthroughКому true. Из-за этой установки и предшествующего ограничения сгенерированная S-функция не может разорвать алгебраические циклы.
Поддерживает только непрерывный, но фиксированный шаг времени, время выборки и опцию смещения.
Поддерживает комплексные номера, но только со встроенными типами данных Simulink.
Не поддерживает использование указателей функций в качестве выходных данных вызываемой устаревшей функции.
Не поддерживает следующие функции S-функции:
Рабочие векторы, отличные от общих векторов DWork
Входные и выходные сигналы на основе кадров
Время выборки на основе порта
Время выборки на основе нескольких блоков
Не поддерживает использование оператора scope (::) для доступа к данным и методам класса C++. Для статических методов можно написать простые макросы препроцессора, похожие на следующие, чтобы обойти это:
#define CCommon_computeVectorDotProduct CCommon::computeVectorDotProduct
Можно создать функцию завершения, если она не указана, если спецификация функции включает тип данных Simulink, имеющий свойство HeaderFile. Для модели функции экспорта эта функция завершения может сделать сгенерированную S-функцию несовместимой с генерацией кода.