Следующие шаги показывают, как инициализировать и использовать векторы DWork в S-функции MEX на C. Полный список SimStruct макросы, относящиеся к векторам DWork, см. DWork Vector C MEX Macros.
В mdlInitializeSizes, задайте количество векторов DWork, использующих ssSetNumDWork макрос. Для примера, чтобы указать, что S-функция содержит два вектора DWork, используйте команду
ssSetNumDWork(S, 2);
Хотя и mdlInitializeSizes метод сообщает Simulink® движком, сколько векторов DWork будет использовать S-функция, движком не выделяется память для векторов DWork, в это время.
S-функция может отложить определение количества векторов DWork до тех пор, пока вся информация о входах S-функции не будет доступна путем передачи значения DYNAMICALLY_SIZED на ssSetNumDWork макрос. Если S-функция задерживает определение количества векторов DWork в mdlInitializeSizes, это должно обеспечить mdlSetWorkWidths метод для настройки векторов DWork.
Если S-функция не обеспечивает mdlSetWorkWidths метод, mdlInitializeSizes метод устанавливает любые применимые атрибуты для каждого вектора DWork. Для примера следующие линии инициализируют ширины и типы данных векторов DWork, инициализированных на предыдущем шаге.
ssSetDWorkWidth(S, 0, 2); ssSetDWorkWidth(S, 1, 1); ssSetDWorkDataType(S, 0, SS_DOUBLE); ssSetDWorkDataType(S, 1, SS_BOOLEAN);
В следующей таблице перечислены атрибуты, которые можно задать для вектора DWork, и показан пример макроса, который устанавливает его. Посмотрите ssSetDWorkRTWStorageClass для получения списка поддерживаемых классов памяти.
| Признак | Макрос |
|---|---|
| Тип данных | |
| Размер | |
| Имя | |
| Тип использования | |
| Числовой тип, действительный или комплексный | |
| Идентификатор Simulink Coder™ | |
| Класс памяти Simulink Coder | |
| Классификатор типа Simulink Coder C | |
В mdlStart, инициализируйте значения любых векторов DWork, которые должны быть установлены только в начале симуляции. Используйте ssGetDWork макрос для извлечения указателя на каждый вектор DWork и инициализации значений. Для примера выполните следующее mdlStart метод инициализирует первый вектор DWork.
static void mdlStart(SimStruct *S)
{
real_T *x = (real_T*) ssGetDWork(S,0);
/* Initialize the first DWork vector */
x[0] = 0;
x[1] = 2;
}
Механизм Simulink выделяет память для вектора DWork перед вызовом mdlStart способ. Потому что mdlStart метод вызывается только один раз в начале симуляции, не используйте его для данных или состояний, которые необходимо повторно инициализировать, например, при повторном включении отключенной подсистемы, содержащей S-функцию.
В mdlInitializeConditions, инициализируйте значения любых векторов DWork, которые необходимо повторно инициализировать в определенных точках симуляции. Механизм выполняет mdlInitializeConditions в начале симуляции и в любое время активируется включенная подсистема, содержащая S-функцию. Смотрите mdlStart пример на предыдущем шаге для команд, используемых для инициализации значений вектора DWork.
В mdlOutputs, mdlUpdate, и т.д., используйте ssGetDWork макрос для извлечения указателя на вектор DWork и использования или обновления значений вектора DWork. Для примера, для вектора DWork, сохраняющего два дискретных состояния, следующее mdlOutputs и mdlUpdate методы вычисляют выход и обновляют значения дискретного состояния.
S-функция, ранее заданная U(element) как (*uPtrs[element]), A, B, C, и D как матрицы пространства состояний для дискретной системы в пространстве состояний.
/* Function: mdlOutputs ==============================================
* Abstract:
* y = Cx + Du
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
if( ssGetDWorkUsageType(S, 0) == SS_DWORK_USED_AS_DSTATE) {
real_T *y = ssGetOutputPortRealSignal(S,0);
real_T *x = (real_T*) ssGetDWork(S, 0);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
UNUSED_ARG(tid); /* not used in single tasking mode */
/* y=Cx+Du */
y[0]=C[0][0]*x[0]+C[0][1]*x[1]+D[0][0]*U(0)+D[0][1]*U(1);
y[1]=C[1][0]*x[0]+C[1][1]*x[1]+D[1][0]*U(0)+D[1][1]*U(1);
}
}
#define MDL_UPDATE
/* Function: mdlUpdate ===============================================
* Abstract:
* xdot = Ax + Bu
*/
static void mdlUpdate(SimStruct *S, int_T tid)
{
real_T tempX[2] = {0.0, 0.0};
real_T *x = (real_T*) ssGetDWork(S, 0);
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
UNUSED_ARG(tid); /* not used in single tasking mode */
/* xdot=Ax+Bu */
tempX[0]=A[0][0]*x[0]+A[0][1]*x[1]+B[0][0]*U(0)+B[0][1]*U(1);
tempX[1]=A[1][0]*x[0]+A[1][1]*x[1]+B[1][0]*U(0)+B[1][1]*U(1);
x[0]=tempX[0];
x[1]=tempX[1];
}
Вы не должны включать какой-либо код в mdlTerminate метод для удаления памяти, используемой для хранения вектора DWork. Точно так же, если вы генерируете inlined код для S-функции, вы не должны писать mdlRTW метод для доступа к вектору DWork в файле TLC. Программа Simulink обрабатывает эти аспекты вектора DWork для вас.
В следующей таблице перечислены макросы C MEX, относящиеся к векторам DWork.
| Макрос | Описание |
|---|---|
ssSetNumDWork | Задайте количество векторов DWork. |
ssGetNumDWork | Запросите количество векторов DWork. |
ssGetDWork | Получите указатель на определенный вектор DWork. |
ssGetDWorkComplexSignal | Определите, является ли определенный вектор DWork вещественным или комплексным. |
ssGetDWorkDataType | Получите тип данных вектора DWork. |
ssGetDWorkName | Получите имя вектора DWork. |
ssGetDWorkRTWIdentifier | Получите идентификатор, используемый для объявления вектора DWork в сгенерированном коде. |
ssGetDWorkRTWIdentifierMustResolveToSignalObject | Укажите, должен ли вектор DWork разрешиться к Simulink.Signal объект в MATLAB® рабочей области. |
ssGetDWorkRTWStorageClass | Получите класс памяти вектора DWork. |
ssGetDWorkRTWTypeQualifier | Получите квалификатор типа C, используемый для объявления вектора DWork в сгенерированном коде. |
ssGetDWorkUsageType | Определите, как вектор DWork используется в S-функции. |
ssGetDWorkUsedAsDState | Определите, сохраняет ли вектор DWork дискретные состояния. |
ssGetDWorkWidth | Получите размер вектора DWork. |
ssSetDWorkComplexSignal | Задайте, являются ли элементы массива вектора DWork вещественными или комплексными. |
ssSetDWorkDataType | Задайте тип данных вектора DWork. |
ssSetDWorkName | Задайте имя вектора DWork. |
ssSetDWorkRTWIdentifier | Укажите идентификатор, используемый для объявления вектора DWork в сгенерированном коде. |
ssSetDWorkRTWIdentifierMustResolveToSignalObject | Укажите, должен ли вектор DWork разрешиться к Simulink.Signal объект. |
ssSetDWorkRTWStorageClass | Укажите класс памяти для вектора DWork. |
ssSetDWorkRTWTypeQualifier | Укажите квалификатор типа C, используемый для объявления вектора DWork в сгенерированном коде. |
ssSetDWorkUsageType | Задайте, как вектор DWork используется в S-функции. |
ssSetDWorkUsedAsDState | Задайте, что вектор DWork хранит значения дискретного состояния. |
ssSetDWorkWidth | Задайте ширину вектора DWork. |
Можно использовать векторы DWork для связи с унаследованным кодом. Если у вас есть код, который выделяет структуры данных в памяти, сохраните указатель на эти структуры данных в векторе DWork. Ваша S-функция может затем связаться с унаследованным кодом через указатель. Кроме того, для простоты настройки S-функции можно использовать рабочий вектор указателя для хранения указателя. Описание рабочих векторов указателя смотрите в Elementary Работы Vectors.
Можно также использовать векторы DWork для хранения состояния унаследованного кода. Файл шаблона sfuntmpl_gate_fortran.c показывает, как использовать векторы DWork для взаимодействия с устаревшим код Фортраном. Legacy Code Tool использует векторы DWork для поддержания состояний устаревших кодов C or C++, встроенных через инструмент. Смотрите Интегрировать функции C с помощью Legacy Code Tool для получения дополнительной информации о Legacy Code Tool.