Следующие шаги показывают, как инициализировать и использовать векторы DWork в C MEX S-функции. Для полного списка 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 список поддерживаемых классов хранения.
| Признак | Макрос |
|---|---|
| Тип данных | |
| Размер | |
| Имя | |
| Тип использования | |
| Числовой тип, вещественный или комплексный | |
| Идентификатор Coder™ Simulink | |
| Класс хранения 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. Аналогичным образом, при создании встроенного кода для 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-функции можно использовать рабочий вектор указателя для хранения указателя. Описание рабочих векторов указателей см. в разделе Элементарные рабочие векторы.
Векторы DWork можно также использовать для сохранения состояния устаревшего кода. Файл шаблона sfuntmpl_gate_fortran.c показывает, как использовать векторы DWork для взаимодействия с устаревшим кодом Fortran. Legacy Code Tool использует векторы DWork для поддержания состояний устаревшего кода C или C++, включенного через инструмент. Дополнительные сведения об инструменте «Устаревший код» см. в разделе Интеграция функций C с помощью инструмента устаревшего кода.