Импорт вызовов во внешний код в сгенерированный код с помощью Legacy Code Tool

Legacy Code Tool и генерация кода

Можно использовать Simulink® Legacy Code Tool для генерации полностью встроенных S-функций C MEX для устаревшего или пользовательского кода. S-функции оптимизированы для встроенных компонентов, таких как драйверы устройств и интерполяционные таблицы, и они вызывают существующие функции C или C++.

Примечание

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

Можно использовать инструмент для:

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

  • Сгенерируйте маскированный блок S-Function, который сконфигурирован для вызова существующего внешнего кода.

Если вы хотите включить эти типы S-функций в модели, для которых вы намерены сгенерировать код, используйте инструмент, чтобы сгенерировать блочный файл TLC. Файл блока TLC задает, как сгенерированный код для модели вызывает существующую функцию C или C++.

Если S-функция зависит от файлов в папках, отличных от папки, содержащей динамически загружаемый исполняемый файл S-функции, используйте инструмент, чтобы сгенерировать sFunction_makecfg.m или rtwmakecfg.m файл для S-функции. Генерация файла поддерживает эти зависимости, когда вы создаете модель, которая включает в себя S-функцию. Для примера для некоторых приложений, таких как пользовательские целевые объекты, можно хотеть найти файлы в конкретном целевом расположении. Процесс сборки ищет sFunction_makecfg.m или rtwmakecfg.m в той же папке, что и динамически загружаемый исполняемый файл S-функции, и вызывает функцию в файле.

Для получения дополнительной информации смотрите Интегрировать функции C с помощью Legacy Code Tool.

Сгенерируйте Inlined S-Function файлы для генерации кода

В зависимости от требований генерации кода вашего приложения, чтобы сгенерировать код для модели, которая использует 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

Вы не можете задать singleCPPMexFile поле к true если

  • Options.language='C++'

  • Вы используете один из следующих объектов Simulink с IsAlias значение свойства установлено в true:

    • Simulink.Bus

    • Simulink.AliasType

    • Simulink.NumericType

  • Спецификация функции Legacy Code Tool включает в себя void* или void** для представления скалярных рабочих данных для аргумента состояния

  • HeaderFiles поле структуры Legacy Code Tool задает несколько заголовочных файлов

Применение настроек стиля кода к устаревшим функциям

Чтобы применить параметры конфигурации модели для стиля кода к унаследованной функции:

  1. Инициализируйте структуру данных Legacy Code Tool. Для примера:

    def = legacy_code('initialize');
    
  2. В структуре данных установите значение Options.singleCPPMexFile поле к true. Для примера:

    def.Options.singleCPPMexFile = true;

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

def.Options.singleCPPMexFile

Ограничения 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-функций для симуляции и генерации кода

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

  • Файл регистрации

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

  • TLC- блока файл

  • sFunction_makecfg.m или rtwmakecfg.m файл

  • Заголовок, источник и включать файлы, от которых зависит сгенерированная S-функция

Когда вы используете эти развернутые файлы:

  • Перед использованием развернутых файлов в модели Simulink добавьте папку, которая содержит файлы S-функций, в MATLAB® путь.

  • Если структура данных Legacy Code Tool регистрирует необходимые файлы как абсолютные пути, и местоположение файлов изменяется, перегенерируйте sFunction_makecfg.m или rtwmakecfg.m файл.

Интеграция внешних объектов C++

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)';

См. также

Похожие темы