Можно интегрировать существующие функции C (или C++), такие как драйверы устройств, интерполяционные таблицы и общие функции и интерфейсы, в Simulink® моделирует при помощи Legacy Code Tool. Использование спецификаций, которые вы поставляете как MATLAB® код, инструмент преобразует существующие функции в S-функции C MEX, которые можно включить в модели Simulink. Если вы используете Simulink Coder™ для генерации кода, Legacy Code Tool может вставить соответствующий вызов вашей функции C в сгенерированный код. Для получения дополнительной информации смотрите Импорт вызовов во внешний код в сгенерированный код с помощью Legacy Code Tool (Simulink Coder).
По сравнению с использованием S-Function Builder или записью 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 и, при необходимости, 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, смотрите Импорт вызовов во внешний код в сгенерированный код с помощью Legacy Code Tool (Simulink Coder) для получения информации об использовании Legacy Code Tool для генерации кода.
Этот пример демонстрирует, как интегрировать существующую функцию C в модель Simulink с помощью Legacy Code Tool.
Предположим, что у вас есть функция C, которая выводит значение ее входного сигнала с плавающей точкой, умноженное на два. Функция определяется в исходном файле с именем doubleIt.c
, и его объявление существует в заголовочном файле с именем doubleIt.h
.
Инициализируйте 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]
Задайте соответствующие значения для полей в структуре данных 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
страница с описанием.
Сгенерируйте исходный файл S-функции из существующей функции C при помощи legacy_code
функция. В командной строке MATLAB введите:
legacy_code('sfcn_cmex_generate', def);
Legacy Code Tool использует информацию, указанную в 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-Function блок в модель Simulink.
legacy_code('slblock_generate', def);
Legacy Code Tool конфигурирует блок, чтобы использовать S-функцию C MEX, созданную на предыдущем шаге. Кроме того, инструмент маскирует блок таким образом, чтобы он отображал значение своего OutputFcnSpec
свойство (см. описание legacy_code
функция).
Добавьте блок амплитуды 1 Sine Wave к входу блока S-функции C-MEX и блок Scope к выходу.
Запустите симуляцию. Блок C-MEX S-Function возвращает значение своего входа с плавающей точкой, умноженное на два. Он ведет себя как функция C doubleIt
.
В этом примере показано, как использовать Legacy Code Tool для интеграции функции C, аргументы которой являются указателями на структуры.
В Simulink ® создайте Simulink.Bus
объект, представляющий тип структуры. Используйте сигналы шины в модели, чтобы представлять структурированные сигналы и состояния. Создайте структуры MATLAB в рабочей области или в диалоговом окне параметров блоков, чтобы представлять структуры параметров.
Для получения основной информации о сигналах шины смотрите Virtual Bus. Для получения основной информации о структурах параметров смотрите Organize Related Block Parameter Definitions in Structures. Для создания объектов шины см. раздел «Создание и определение объектов 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-Function, который вызывает S-функцию во время симуляции.
legacy_code('slblock_generate', def);
Блок появляется в новой модели.
Чтобы использовать блок S-Function в вашей модели, создайте сигнал шины типа sigStructType
для использования в качестве блока входных параметров. Блок выводит также сигнал шины. Маска блока принимает параметр, P1. Чтобы задать значение параметра, используйте структуру MATLAB, поля которой совпадают с полями типа структуры paramStructType
.
Проверьте выполнение внешнего кода
Создайте модель тестовой обвязки, которая проверяет выполнение внешнего кода во время симуляции.
Для примера просмотрите модель ex_lct_struct
.
open_system('ex_lct_struct')
В диалоговое окно блока Constant параметр Constant значения устанавливается на структуру, поля которой совпадают с полями типа структуры sigStructType
. На вкладке Signal Attributes Выхода тип данных устанавливается на объект шины sigStructType
.
Блок S-Function вызывает S-функцию sfun_ex_mySrc_LCT
который вы создали. Выход блока входит в блок Bus Selector, который извлекает сигнальные элементы 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')
Симулируйте модель. Блоки Возможностей показывают, что блок S-Function вызывает внешнюю функцию myFcn
.
open_system('ex_lct_struct/Scope') open_system('ex_lct_struct/Scope1') sim('ex_lct_struct') %
Первым шагом к использованию Legacy Code Tool является регистрация одной или нескольких структур MATLAB с полями, которые представляют свойства существующего кода С и генерируемой S-функции. Процесс регистрации является гибким. Вы можете принять решение настроить ресурсы и инициировать регистрацию различными способами, включая
Размещение всех необходимых заголовков и исходных файлов в текущей рабочей папке или в иерархической структуре папки
Генерация и размещение одной или нескольких S-функций в текущей рабочей папке
Наличие одного или нескольких файлов регистрации в одной папке
Чтобы зарегистрировать структуру данных Legacy Code Tool:
Используйте 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]
Задайте значения для полей структуры данных (свойств), которые применяются к существующей функции C и S-функции, которую вы намереваетесь сгенерировать. Минимально, вы должны задать
Исходные файлы и заголовки для существующей функции C (SourceFiles
и HeaderFiles
)
Имя для S-функции (SFunctionName
)
По крайней мере, одна спецификация функции для S-функции (InitializeConditionsFcnSpec
, OutputFcnSpec
, StartFcnSpec
, TerminateFcnSpec
)
Полный список и описание полей в структуре см. в разделе legacy_code
страница с описанием функции.
Если вы задаете поля, которые задают ресурсы компиляции и задаете относительные пути, Legacy Code Tool ищет ресурсы относительно следующих директорий в следующем порядке:
Текущая рабочая папка
Папка S-функции C-MEX, если отличается от текущей рабочей папки
Директории, которые вы задаете
IncPaths
для заголовочных файлов
SrcPaths
для исходных файлов
LibPaths
для целевых и хост-библиотек
Директории в пути поиска файлов MATLAB, исключая директории тулбокса
The 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
| Тип данных, перечисленный в Поддерживаемые типы данных. |
| Лексема формы y1 , y2 , ... , y n, где n - общее количество выходных аргументов. |
Если функция не возвращает значение, можно опустить спецификацию возврата или указать ее как void
.
В следующей таблице показан действительный синтаксис спецификации функции для целочисленного возвращаемого значения. Используйте таблицу, чтобы идентифицировать синтаксис, который вы должны использовать для прототипа функции C.
Тип возврата | Прототип функции C | Спецификация функции Legacy Code Tool |
---|---|---|
Нет возвращаемого значения | 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)'
Используя эту спецификацию функции, Legacy Code Tool сопоставляет следующую информацию.
Возвращаемое значение или аргумент | типа 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-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 | Да | Да | Да |
Фиксированная точка4 | Да | Да | Да |
Объекты Fi | Н/Д | Да | Н/Д |
Комплексные числа5 | Да | Да | Да |
1-D массив | Да | Да | Да |
2-D массив6 | Да | Да | Да |
n-D массив7 | Да | Да | Да |
void * | Нет | Нет | Да |
void * * | Нет | Нет | Да |
Вы должны предоставить заголовочный файл, который определяет структуру шины, задает enum
type или определяет тип данных с таким же именем, как и псевдоним. Структура шины, объявленная в заголовочном файле, должна совпадать со структурой объекта шины (для примера, количество и порядок элементов, типы данных и ширины элементов и так далее). Для получения примера смотрите Использование шин с устаревшими функциями, имеющими аргументы структуры.
Чтобы сгенерировать объекты типа данных и классы перечисления, которые соответствуют пользовательским типам данных, заданным вашим кодом С, используйте 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 с помощью Legacy Code Tool, функция должна соответствовать следующим правилам:
Функция не должна изменять значение входных параметров. Если входной сигнал является переданным по ссылке аргументом функции, функция не должна изменять данные, на которые указывает аргумент.
Возвращаемое значение функции не может быть указателем.
Спецификации функций, которые вы определяете для StartFcnSpec
, InitializeConditionsFcnSpec
, или TerminateFcnSpec
не удается получить доступ к входным или выходным аргументам. Для StartFcnSpec
и InitializeConditionsFcnSpec
, вы можете получить доступ к выходным портам, если опция S-Function outputsConditionallyWritten
установлено в true
. С помощью этой настройки опции сгенерированная S-функция задает, что память, связанная с каждым выходам портом, не может быть перезаписана и является глобальной (SS_NOT_REUSABLE_AND_GLOBAL
).
После регистрации структуры данных Legacy Code Tool для существующей функции C используйте legacy_code
функция, как объяснено ниже, чтобы сгенерировать, скомпилировать и связать S-функцию.
Сгенерируйте S-функцию MEX на основе информации, определенной в структуре. Звонить legacy_code
с 'sfcn_cmex_generate'
как первый аргумент и имя структуры данных как второй аргумент.
legacy_code('sfcn_cmex_generate', lct_spec);
Скомпилируйте и соедините S-функцию. Этот шаг предполагает, что для установки MATLAB настроен компилятор C. Звонить 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-функцию.
У вас есть опция использовать Legacy Code Tool, чтобы сгенерировать блок s-function (графическое представление), который сконфигурирован для вызова сгенерированной S-функции C MEX. Чтобы сгенерировать такой блок, вызовите 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, можно сгенерировать и принудительно использовать инлайнинговый код TLC для S-функции, сгенерированной Legacy Code Tool. Для этого:
Сгенерируйте файл блока 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);
Заставьте Режим Accelerator использовать 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++. Для получения дополнительной информации см. раздел «Ограничения 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-функции, которые вы генерируете с помощью Legacy Code Tool для использования другими. Чтобы развернуть S-функцию только для использования в симуляции, необходимо совместно использовать только скомпилированный динамически загружаемый исполняемый файл.
Для примеров Legacy Code Tool, смотрите Реализуйте Алгоритмы Используя Legacy Code Tool.
Legacy Code Tool
Генерирует S-функции на C MEX для существующих функций, написанных на C или C++. Инструмент не поддерживает преобразование функций MATLAB или Фортран.
Может взаимодействовать с функциями C++, но не с объектами C++. Один из способов преодоления этого ограничения - использовать S-Function Builder, чтобы сгенерировать интерпретатор S-функции, а затем вызвать устаревший код С++ из 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-функцию несовместимой с генерацией кода.