В этом примере показано, как использовать блок C Caller с условным выполнением. Модель в качестве примера содержит два блока Вызывающей стороны C, выходные параметры которых вводятся ветви в блок switch. Каждый блок C Caller вызывает одну из пользовательских функций кода С sort_ascend() и sort_descend(). Только одно из значений от входных ветвей передается выходной стороне блока switch. Функциональный блок C с теми же настройками может также использоваться вместо блока C Caller, чтобы вызвать эти функции пользовательского кода.
Этот пример иллюстрирует следующие концепции:
Вызов пользовательского кода С от Simulink® блокируется в условном контексте выполнения.
Конфигурирование детерминированных функций функцией в пользовательском коде.
Эта модель вызывает пользовательский код через блок C Caller, который соединяется с входной ветвью блока switch.
open_system('slexCCallerConditional'); % Create a temporary folder for the build and inspection process. currentDir=pwd; [~,cgDir]=rtwdemodir();

Функции пользовательского кода в этой модели не были идентифицированы как детерминированные функции. Когда код сгенерирован из модели, и функции C выполняются в процессе моделирования и в сгенерированном коде, даже при том, что блок switch требует выхода только одной из функций.
slbuild(bdroot); cfile = fullfile(cgDir,'slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); rtwdemodbtype(cfile,'/* Model step', '/* Matfile logging', 1, 0);
### Starting build procedure for: slexCCallerConditional
### Successful completion of build procedure for: slexCCallerConditional
Build Summary
Top model targets built:
Model Action Rebuild Reason
=======================================================================================================
slexCCallerConditional Code generated and compiled Code generation information file does not exist.
1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 28.521s
/* Model step function */
void slexCCallerConditional_step(void)
{
real_T rtb_CCallerascend[6];
real_T rtb_CCallerdescend[6];
int32_T i;
/* CCaller: '<Root>/C Caller (ascend)' incorporates:
* Inport: '<Root>/In2'
*/
for (i = 0; i < 6; i++) {
rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i];
}
sort_ascend(&rtb_CCallerascend[0], 6);
/* End of CCaller: '<Root>/C Caller (ascend)' */
/* CCaller: '<Root>/C Caller (descend)' incorporates:
* Inport: '<Root>/In2'
*/
for (i = 0; i < 6; i++) {
rtb_CCallerdescend[i] = slexCCallerConditional_U.In2[i];
}
sort_descend(&rtb_CCallerdescend[0], 6);
/* End of CCaller: '<Root>/C Caller (descend)' */
for (i = 0; i < 6; i++) {
/* Switch: '<Root>/Switch' incorporates:
* Inport: '<Root>/In1'
*/
if (slexCCallerConditional_U.In1 > 0.0) {
/* Outport: '<Root>/Out3' */
slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i];
} else {
/* Outport: '<Root>/Out3' */
slexCCallerConditional_Y.Out3[i] = rtb_CCallerdescend[i];
}
/* End of Switch: '<Root>/Switch' */
}
Откройте диалоговое окно Configuration Parameters.
В Целевой панели Симуляции, набор Детерминированные функции к By Function. Нажмите Specify функцией и добавьте функции sort_ascend и sort_descend к списку. Это действие говорит модели, что заданные функции пользовательского кода имеют детерминированное поведение, то есть, те же входные значения к функциям всегда дают те же выходные параметры. Если функция собирается быть детерминированной, она не должна быть названа, если это находится во входной ветви, соответствующей ложному значению блока switch.


configset.highlightParameter(bdroot,'DefaultCustomCodeDeterministicFunctions'); set_param(bdroot,'DefaultCustomCodeDeterministicFunctions','ByFunction'); set_param(bdroot,'CustomCodeDeterministicFunctions','sort_ascend,sort_descend');
Теперь, когда вы задали детерминированные функции, сгенерированный код более эффективен, потому что только блок C Caller в истинной ветви блока switch выполняется. Тот же КПД применяется, когда вы симулируете модель в Simulink.
slbuild(bdroot); cfile = fullfile(cgDir,'slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); rtwdemodbtype(cfile,'/* Model step', '/* Matfile logging', 1, 0); close_system(bdroot, 0);
### Starting build procedure for: slexCCallerConditional
### Successful completion of build procedure for: slexCCallerConditional
Build Summary
Top model targets built:
Model Action Rebuild Reason
======================================================================================
slexCCallerConditional Code generated and compiled Generated code was out of date.
1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 12.802s
/* Model step function */
void slexCCallerConditional_step(void)
{
real_T rtb_CCallerascend[6];
int32_T i;
/* Switch: '<Root>/Switch' incorporates:
* Inport: '<Root>/In1'
*/
if (slexCCallerConditional_U.In1 > 0.0) {
/* CCaller: '<Root>/C Caller (ascend)' incorporates:
* Inport: '<Root>/In2'
*/
for (i = 0; i < 6; i++) {
rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i];
}
sort_ascend(&rtb_CCallerascend[0], 6);
/* End of CCaller: '<Root>/C Caller (ascend)' */
} else {
/* CCaller: '<Root>/C Caller (descend)' incorporates:
* Inport: '<Root>/In2'
*/
for (i = 0; i < 6; i++) {
rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i];
}
sort_descend(&rtb_CCallerascend[0], 6);
/* End of CCaller: '<Root>/C Caller (descend)' */
}
/* End of Switch: '<Root>/Switch' */
/* Outport: '<Root>/Out3' */
for (i = 0; i < 6; i++) {
slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i];
}
/* End of Outport: '<Root>/Out3' */
Детерминированные функции | Задайте функцией | C Function | C Caller