Можно использовать Simulink® Legacy Code Tool для генерации полностью встроенных S-функций C MEX для устаревшего или пользовательского кода. S-функции оптимизированы для встроенных компонентов, таких как драйверы устройств и интерполяционные таблицы, и они вызывают существующие функции C или C++.
Примечание
Legacy Code Tool может взаимодействовать с функциями C++, но не с объектами C++. Чтобы решить эту проблему, чтобы инструмент мог взаимодействовать с объектами C++, смотрите Ограничения Legacy Code Tool.
Можно использовать инструмент для:
Если вы хотите включить эти типы S-функций в модели, для которых вы намерены сгенерировать код, используйте инструмент, чтобы сгенерировать блочный файл TLC. Файл блока TLC задает, как сгенерированный код для модели вызывает существующую функцию C или C++.
Если S-функция зависит от файлов в папках, отличных от папки, содержащей динамически загружаемый исполняемый файл S-функции, используйте инструмент, чтобы сгенерировать sFunction
_makecfg.m
или rtwmakecfg.m
файл для S-функции. Генерация файла поддерживает эти зависимости, когда вы создаете модель, которая включает в себя S-функцию. Для примера для некоторых приложений, таких как пользовательские целевые объекты, можно хотеть найти файлы в конкретном целевом расположении. Процесс сборки ищет sFunction
_makecfg.m
или rtwmakecfg.m
в той же папке, что и динамически загружаемый исполняемый файл S-функции, и вызывает функцию в файле.
Для получения дополнительной информации смотрите Интегрировать функции C с помощью Legacy Code Tool.
В зависимости от требований генерации кода вашего приложения, чтобы сгенерировать код для модели, которая использует S-функцию, выполните одно из следующих действий:
Сгенерируйте одну .cpp
файл для встроенной S-функции. В структуре данных Legacy Code Tool задайте значение Options.singleCPPMexFile
поле к true
перед сгенерированием исходного файла S-функции из существующей функции C. Для примера:
def.Options.singleCPPMexFile = true; legacy_code('sfcn_cmex_generate', def);
Сгенерируйте исходный файл и файл блока TLC для встроенной S-функции. Для примера:
def.Options.singleCPPMexFile = false; legacy_code('sfcn_cmex_generate', def); legacy_code('sfcn_tlc_generate', def);
Вы не можете задать singleCPPMexFile
поле к true
если
Options.language='C++'
Вы используете один из следующих объектов Simulink с IsAlias
значение свойства установлено в true
:
Simulink.Bus
Simulink.AliasType
Simulink.NumericType
Спецификация функции Legacy Code Tool включает в себя void*
или void**
для представления скалярных рабочих данных для аргумента состояния
HeaderFiles
поле структуры Legacy Code Tool задает несколько заголовочных файлов
Чтобы применить параметры конфигурации модели для стиля кода к унаследованной функции:
Инициализируйте структуру данных Legacy Code Tool. Для примера:
def = legacy_code('initialize');
В структуре данных установите значение Options.singleCPPMexFile
поле к true
. Для примера:
def.Options.singleCPPMexFile = true;
Чтобы проверить настройку, введите:
def.Options.singleCPPMexFile
Вы не можете задать singleCPPMexFile
поле к true
если
Options.language='C++'
Вы используете один из следующих объектов Simulink с IsAlias
значение свойства установлено в true
:
Simulink.Bus
Simulink.AliasType
Simulink.NumericType
Спецификация функции Legacy Code Tool включает в себя void*
или void**
для представления скалярных рабочих данных для аргумента состояния
HeaderFiles
поле структуры Legacy Code Tool задает несколько заголовочных файлов
По умолчанию Legacy Code Tool предполагает, что файлы, от которых зависит S-функция, находятся в той же папке, что и динамически загружаемый исполняемый файл для S-функции. Если ваша S-функция зависит от файлов, которые находятся в другом месте, и вы используете процесс сборки шаблона make-файла, сгенерируйте sFunction
_makecfg.m
или rtwmakecfg.m
файл для S-функции. Для примера можно сгенерировать этот файл, если структура данных Legacy Code Tool определяет ресурсы компиляции как имена путей.
Чтобы сгенерировать sFunction
_makecfg.m
или rtwmakecfg.m
файл, вызвать legacy_code
функция со 'sfcn_makecfg_generate'
или 'rtwmakecfg_generate'
в качестве первого аргумента и имени структуры данных Legacy Code Tool в качестве второго аргумента. Для примера:
legacy_code('sfcn_makecfg_generate', lct_spec);
Если вы используете несколько файлов регистрации в одной папке и генерируете S-функцию для каждого файла с одним вызовом в legacy_code
, вызов на legacy_code
который задает 'sfcn_makecfg_generate'
или 'rtwmakecfg_generate'
должен быть общим для всех файлов регистрации. Для получения дополнительной информации см. Раздел «Обработка нескольких файлов регистрации».
Для примера, если вы задаете defs
как массив структур Legacy Code Tool, вы вызываете legacy_code
с 'sfcn_makecfg_generate'
один раз.
defs = [defs1(:);defs2(:);defs3(:)]; legacy_code('sfcn_makecfg_generate', defs);
Для получения дополнительной информации смотрите Поддержка сборки для S-функций.
Можно развернуть S-функции, которые вы генерируете с помощью Legacy Code Tool, чтобы другие люди могли использовать их. Чтобы развернуть S-функцию для симуляции и генерации кода, поделитесь следующими файлами:
Файл регистрации
Скомпилированный динамически загружаемый исполняемый файл
TLC- блока файл
sFunction
_makecfg.m
или rtwmakecfg.m
файл
Заголовок, источник и включать файлы, от которых зависит сгенерированная S-функция
Когда вы используете эти развернутые файлы:
Перед использованием развернутых файлов в модели Simulink добавьте папку, которая содержит файлы S-функций, в MATLAB® путь.
Если структура данных Legacy Code Tool регистрирует необходимые файлы как абсолютные пути, и местоположение файлов изменяется, перегенерируйте sFunction
_makecfg.m
или rtwmakecfg.m
файл.
Legacy Code Tool может взаимодействовать с функциями C++, но не с объектами C++. Используя предыдущий пример в качестве начальной точки, вот пример того, как можно обойти это ограничение.
Измените определение класса для adder
в новом файле adder_cpp.hpp
. Добавьте три новых макроса, которые динамически выделяют новую adder
объект, активируйте метод add_one()
, и освободить выделенную память. Каждый макрос принимает указатель на adder
объект. Поскольку каждая функция, вызываемая Legacy Code Tool, должна иметь C-подобную сигнатуру, указатель кэшируется и передается как void*
. Затем вы должны явным образом привести к adder*
в макросе. Новое определение класса для adder
:
#ifndef _ADDER_CPP_ #define _ADDER_CPP_ class adder { private: int int_state; public: adder(): int_state(0) {}; int add_one(int increment); int get_val() {return int_state;}; }; // Method wrappers implemented as macros #define createAdder(work1) \ *(work1) = new adder #define deleteAdder(work1) \ delete(static_cast<adder*>(*(work1))) #define adderOutput(work1, u1) \ (static_cast<adder*> ((work1)))->add_one(u1) #endif /* _ADDER_CPP_ */
Обновление adder_cpp.cpp
. С изменением класса, вместо одного глобального образца, каждая сгенерированная S-функция управляет своей adder
объект.
#include "adder_cpp.hpp" int adder::add_one(int increment) { int_state += increment; return int_state; }
Обновление rtwdemo_sfun_adder_cpp.cpp
со следующими изменениями:
StartFcnSpec
вызывает макрос, который выделяет новую adder
объект и кэширует указатель.
def.StartFcnSpec = 'createAdder(void **work1)';
OutputFcnSpec
вызывает макрос, который вызывает метод add_one()
и обеспечивает специфическую для S-функции adder
объект.
def.OutputFcnSpec = 'int32 y1 = adderOutput(void *work1, int32 u1)';
TerminateFcnSpec
вызывает макрос, который освобождает память.
def.TerminateFcnSpec = 'deleteAdder(void **work1)';