exponenta event banner

Интеграция кода C с использованием блоков вызывающего абонента C

Новый или существующий код C можно интегрировать в Simulink ® с помощью блока C Caller. Для создания пользовательских блоков в моделях Simulink блок C Caller позволяет вызывать внешние функции C, указанные во внешнем исходном коде и библиотеках. Преимущества блока C Caller:

  • Автоматизированная интеграция простых функций C

  • Интеграция с Simulink Coverage™, Simulink Test™ и Simulink Design Verifier™

  • Интеграция с Simulink Coder™

Блок C Caller позволяет вводить алгоритмы C в Simulink. Для моделирования динамических систем используйте S-Function Builder. Далее описывается процесс интеграции кода C в Simulink с использованием блока C Caller.

Укажите исходный код и зависимости

Укажите внешний файл исходного кода, содержащий функции C.

  1. На панели инструментов Simulink откройте окно «Параметры конфигурации».

  2. На левой панели выберите «Цель моделирования».

  3. Чтобы включить синтаксический анализ кода блоком C Caller, убедитесь, что выбрано поле Import custom code.

    Каталоги и пути к файлам могут быть абсолютными и относительными к каталогам модели или к текущей рабочей папке. См. раздел Указание относительных путей к пользовательскому коду (поток состояний).

  4. Выберите Верхний колонтитул и введите имя верхнего колонтитула с помощью #include тег.

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

  6. Выберите Исходные файлы и введите путь и имя исходного файла. Если файл модели и исходный файл находятся в разных каталогах, перед именем файла введите каталог, содержащий исходный файл.

Примечание

Если функция объявлена в файле заголовка, но не реализована в исходном коде, для моделирования и компиляции модели автоматически генерируется пустая функция-заглушка.

Примечание

Для использования блока C Caller в подсистеме For Each или с непрерывным временем выборки или для оптимизации использования блока при выполнении условной ветви ввода пользовательская кодовая функция, вызываемая блоком, должна быть детерминированной, то есть всегда создавать одинаковые выходы для одних и тех же входов. Определите, какие пользовательские функции кода являются детерминированными, используя функции Детерминированные (Deterministic) и Указать по параметрам функции (Specify by function parameters) на целевой панели Моделирование (Simulation). Пример выполнения условного входа ветви см. в разделе Использование блока вызывающего абонента C с условным выполнением.

Определение формата массива функций по умолчанию

Можно указать порядок хранения матричных данных в Simulink. Данные матрицы, передаваемые в и из функций C, преобразуются в формат массива функций по умолчанию. Если компоновка массива функций не указана, данные матрицы передаются через C-вызывающего абонента в том же порядке, что и данные Simulink, и вычислительные ошибки могут возникать из-за основного сбоя столбца строки. Убедитесь, что для всех данных Simulink используется одинаковая компоновка массива функций по умолчанию.

  • Column-Major - блок C Caller обрабатывает данные Simulink в мажорном порядке. Предположим, что у вас есть матрица 3 на 3. В блоке C Caller эта матрица хранится в следующей последовательности: первый столбец, второй столбец и третий столбец.

  • Строка-мажор - блок C Caller обрабатывает данные Simulink в порядке строка-мажор. Предположим, что у вас есть матрица 3 на 3. В блоке C Caller эта матрица хранится в следующей последовательности: первая строка, вторая строка и третья строка.

  • Любой - данные массива могут храниться как в мажорном, так и в мажорном порядке в блоке C Caller. В результате можно создать код как в основных параметрах столбца, так и в основных параметрах строки.

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

Дополнительные сведения о компоновках массива «строка-основная» и «столбец-основная» в Simulink см. в разделе Компоновка массива функций по умолчанию.

  1. Выберите параметр компоновки массива в разделе Компоновка функции массива по умолчанию.

  2. Если необходимо применить определенный макет массива к некоторым функциям в коде, щелкните Указать по функции (Specify by Function), чтобы выбрать эти функции.

  3. Нажмите кнопку «» Применить «», чтобы принять изменения.

  4. Нажмите кнопку ОК, чтобы закрыть окно Параметры конфигурации (Configuration Parameters).

Блокировка вызова C и определение портов

Можно начать пользовательскую интеграцию кода C в Simulink, введя C Caller в холсте Simulink. Можно также перетащить блок вызывающего абонента C из обозревателя библиотек > Пользовательские функции. Дважды щелкните блок, чтобы открыть диалоговое окно «Параметры блока» для просмотра имен функций и спецификаций портов.

  1. Щелкните Обновить пользовательский код, чтобы импортировать исходный код и его зависимости.

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

  3. Для просмотра определений функций в исходном файле нажмите кнопку. Исходный код выбранной функции отображается в редакторе MATLAB ®. Если исходный код недоступен, отображается объявление функции в файле заголовка.

  4. Чтобы изменить исходные файлы и их зависимости, или определить и выбрать макеты массива функций, щелкните Настройки пользовательского кода , чтобы открыть вкладку Цель моделирования в параметрах конфигурации.

Сопоставить аргументы функции C портам Simulink

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

extern void mean_filter(const unsigned char* src,
                           unsigned char* dst,
                           unsigned int width, unsigned int height,
                           unsigned int filterSize);

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

Имя (Name) - указывает имя входных и выходных аргументов. Имя - это аргумент функции или имя параметра, определенное в функциях C из исходного кода. Этот столбец предназначен только для справочных целей.

Область - указывает, как аргументы функции C сопоставляются с областью Simulink. Аргументы имеют области по умолчанию в зависимости от определения функции, и можно изменять области в зависимости от определения функции в исходном коде.

Область SimulinkОбласть для отображения блоков
InputВходной порт блока
OutputВыходной порт блока
InputOutputВходной и выходной порт блока
GlobalГлобальная переменная, используемая блоком
ParameterНастраиваемый параметр блока
ConstantПостоянное значение

Для аргумента, передаваемого указателем, при наличии определения квалификатора константы, например const double *u, аргумент может быть только входным параметром или параметром. Если не существует постоянного квалификатора, аргумент является InputOutput по умолчанию, и вы можете изменить его на Input, Output, или Parameter сфера применения. В случае Input или Parameter убедитесь, что функция C не изменяет память, указанную указателем. Если аргумент имеет значение Output scope, каждый элемент, на который указывает этот указатель, должен быть переназначен в каждом вызове функции.

Аргумент C

Область Simulink

Возврат функции

Output

double u

Input, Parameter, Constant

double *u

double u[]

double u[][2]

double u[2][3]

InputOutput (по умолчанию), Output, Input, Parameter

const double *u

const double u[]

const double u[][2]

const double u[2][3]

Input (по умолчанию), Parameter

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

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

extern void mean_filter(unsigned char* src,
                           unsigned int width, unsigned int height,
                           unsigned int filterSize);

Затем выберите спецификацию порта для InputOutput в таблице Port Specification и назначьте результирующий вывод функции входной переменной в пользовательской функции.

В пользовательском коде можно использовать глобальные переменные, сопоставляя их с соответствующей областью Simulink. Чтобы включить использование глобальных переменных в модели, выберите Включить глобальные переменные как интерфейсы функций в меню Настройки модели > Параметры конфигурации > Цель моделирования. Можно сопоставить глобальные переменные с Input, Output, InputOutput или Global область в блоке C Caller. Доступность этих областей зависит от использования глобальной переменной в пользовательском коде.

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

Пример кодаОбласть Simulink

double data;

void foo(void)
    {
        int temp = data;  
    }

Данные глобальной переменной считывают только переменную data. Доступные области:

Input (по умолчанию)

Global

double data;

void bar(void)
    {
        data = 0;
    }

Данные записываются в глобальную переменную. Доступные области:

Output (по умолчанию)

Global

InputOutput

double data;

void foo2(void)
    {
        data = data + 1;
    }

Данные считываются и записываются в глобальную переменную. Доступные области:

Global (по умолчанию)

InputOutput

Output

Метка - указывает метку для соответствующего аргумента в блоке Simulink. По умолчанию метка аргумента совпадает с именем аргумента, если его не изменить.

Область SimulinkМетка порта Simulink

input, output

Имя порта
inputoutputИмя порта как во входном, так и в выходном порту
GlobalИмя порта и имя глобальной переменной

parameter

Имя параметра

constant

Выражение для значения константы.

выражения размера, использующие, например, имена входных аргументов size(in1,1)

Тип (Type) - демонстрирует соответствие между типом данных Simulink и типом данных аргумента функции C.

Тип данных аргумента CТип данных Simulink
подписанный символint8
неподписанный символuint8
случайная работаint8 или uint8, в зависимости от компилятора
int *int32
неподписанная int *uint32
короткий *int16
длинный *int32 или fixdt (1,64,0), в зависимости от операционной системы
плаваниеодинок
дваждыдважды
int8_t *int8
uint8_t *int8
int16_t *int16
uint16_t *uint16
int32_t *int32
uint32_t *uint32
typedef struct {...} AStruct * *Автобус: AStruct
typedef enum {..} AnEnum * *Перечисление: AnEnum

* Если вызывающий абонент C принимает целочисленный тип, например, int16_t, его можно изменить на тип с фиксированной точкой с соответствующим базовым типом, например, fixdt (1, 16, 3).

* * Кнопка синхронизации C Caller предлагает импортировать типы структуры или перечисления, используемые функцией C в качестве типов шины и перечисления Simulink.

Размер - указывает размеры данных в аргументе.

Измерения аргумента CРазмеры порта Simulink

double u

скаляр (1)

double u[]

double u[][2]

наследуется (-1) (по умолчанию)

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

double *u

наследуется (-1) (по умолчанию)

Если аргумент для inputoutput , размер не может быть унаследован, даже если размер в output порт может наследоваться.

Для глобальных переменных размер является скалярным (1).

double u[2][3]

Размер - [2, 3].

Создать FunctionPortSpecification Объект и редактирование свойств блока вызывающего абонента C

Для программного изменения свойств таблицы спецификации портов можно создать FunctionPortSpecification и изменить его свойства. Создание FunctionPortSpecification для выбранного блока C Caller в модели введите в командной строке:

myCCallerConfigObj = get_param(gcb, 'FunctionPortSpecification')
myCCallerConfigObj = 

  FunctionPortSpecification with properties:

        CPrototype:  'real_T add(real_T u1, real_T u2);'
    InputArguments:  [1×2 Simulink.CustomCode.FunctionArgument]
    ReturnArgument:  [1×1 Simulink.CustomCode.FunctionArgument] 
    GlobalArguments: [1×0 Simulink.CustomCode.FunctionArgument]
CPrototype свойство доступно только для чтения и отображает объявление входных переменных функции C. InputArgument и ReturnArgument свойства создают FunctionArgument для дальнейшего редактирования его свойств в соответствии с правилами, определенными для приведенной выше таблицы Спецификация порта (Port Specification). Вы можете видеть FunctionPortSpecification чтобы узнать больше.

Чтобы изменить глобальные аргументы в блоке вызывающего абонента C, создайте дескриптор GlobalArguments объект с использованием getGlobalArg и измените его свойства.

Создание пользовательской библиотеки вызывающих абонентов C

Можно создать библиотечную модель для группировки блоков C-вызывающих и сохранения упорядоченности моделей.

  1. Откройте новую модель библиотеки. На вкладке «Моделирование» выберите «Создать» > «Библиотека».

  2. На вкладке «Моделирование» в разделе «Модель» выберите «Моделирование» «Пользовательский код».

  3. Выбрать C или C++ в опции Язык (Language) в зависимости от кода и убедитесь, что выбрано поле Импорт пользовательского кода (Import custom code).

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

  5. Создание блоков вызывающего абонента C для вызова функций C.

  6. Чтобы вставить блок из библиотечной модели в модель Simulink, просто перетащите блок в модель.

Создание символов отладки для пользовательского кода

Чтобы подключить внешний отладчик к процессу MATLAB и отладить внешний код C, создайте символы отладки, используя:

Simulink.CustomCode.debugSymbols('on')
После включения этой настройки и обновления модели генерируются символы отладки, и к процессу MATLAB можно подключить внешний отладчик.

Отключить этот параметр с помощью:

Simulink.CustomCode.debugSymbols('off')

Моделирование пользовательского кода в отдельном процессе

При моделировании модели, содержащей пользовательский код C или C++, можно выполнить пользовательский код в отдельном процессе вне MATLAB. Этот параметр может быть полезен при отладке пользовательского кода. При выполнении в отдельном процессе проблемы с пользовательским кодом не приводят к аварийному завершению работы MATLAB, что упрощает отладку и устранение таких проблем. Проблемы могут возникнуть из-за непредвиденных исключений в пользовательском коде или ошибок в интерфейсе между Simulink и пользовательским кодом.

Чтобы включить эту опцию, в параметрах конфигурации модели на панели Цель моделирования (Simulation target) выберите Моделировать пользовательский код (Simulate custom code) в отдельном процессе. Опция применяется к пользовательскому коду C/C + +, интегрированному в модель с использованием любого из следующих блоков:

  • Вызывающий абонент C

  • Функция C

  • Функция MATLAB

  • Система MATLAB

  • Диаграмма Stateflow ®

The Simulation Target pane of the Configuration Parameters dialog. The pane shows a checkbox for 'Simulate custom code in a separate process' parameter.

Например, эта модель содержит блок вызывающего абонента C, который вызывает функцию adder(), который обращается к объекту с именем adderObj. Перед вызовом функции необходимо создать объект, что можно сделать путем вызова initAdder() в функции Инициализация (Initialize) панели Цель моделирования (Simulation Target) параметров конфигурации модели.

part of Simulink model canvas including C Caller block with "adder" on the block icon

static Adder* adderObj = nullptr;

int adder(int increment)
{
    adderObj->add_one(increment);
    return adderObj->get_val();
}

void initAdder()
{
    adderObj = new Adder();
}

Если initAdder() не вызывается ранее adder(), то adder() пытается получить доступ к неинициализированному указателю, что приводит к исключению во время выполнения. Если пользовательский код Simulate в отдельном параметре процесса не выбран, это исключение может привести к сбою MATLAB при моделировании модели. Однако если параметр выбран, при моделировании модели в Simulink появляется сообщение об ошибке.

Error message text

Затем можно нажать кнопку Открыть, чтобы запустить внешний отладчик и устранить проблему, вызвавшую ошибку.

external debugger showing custom C code with breakpoints set

После запуска отладчика он перезапустит моделирование и автоматически остановится в точках останова пользовательских записей функций.

После полной отладки пользовательского кода можно отменить выбор пользовательского кода Simulate в отдельном процессе для ускорения моделирования.

Ограничения

  • Глобальные переменные - глобальные переменные как входы функции не поддерживают многомерные массивы.

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

  • Поддержка сложных данных - блок C Caller не поддерживает сложные типы данных в Simulink.

  • Переменные аргументы - переменные аргументы в языке C не поддерживаются, например, int sprintf(char *str, const char *format, ...).

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

Сведения о тестировании моделей, включающих блоки вызывающего абонента C, см. в разделе Тестирование интегрированного кода C (Simulink Test).

Примечание

Если модель имеет пользовательский код, после обновления или запуска модели slprj может быть заблокирована из-за загруженного исполняемого файла моделирования пользовательского кода. Невозможно удалить папку, когда она заблокирована. Чтобы выгрузить исполняемый файл и разблокировать slprj , используйте clear mex команда. Посмотрите clear.

См. также

| | | | | | | |

Связанные темы