В этом примере показано, как использовать блок вызывающего абонента C с условным выполнением. Пример модели содержит два блока C Caller, выходы которых являются входными ветвями блока Switch. Каждый блок вызывающего абонента C вызывает одну из пользовательских функций кода C sort_ascend() и sort_descend(). Только одно из значений из входных ветвей передается на выходную сторону блока коммутатора. Функциональный блок C с теми же настройками может также использоваться вместо блока C вызывающего абонента для вызова этих пользовательских функций кода.
Этот пример иллюстрирует следующие концепции:
Вызов пользовательского кода C из блока Simulink ® в контексте условного выполнения.
Настройка детерминированных функций по функциям в пользовательском коде.
Эта модель вызывает пользовательский код через блок вызывающего абонента C, который подключен к входной ветви блока коммутатора.
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 25.644s
/* 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, 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, 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' */
}
Откройте диалоговое окно «Параметры конфигурации».
На панели Цель моделирования (Simulation Target) в группе Импорт пользовательского кода (Import Custom Code) задайте для функций Determinitic значение By function. Щелкните Указать по функции (Specify by Function) и добавьте функции. 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 10.423s
/* 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, 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, 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 | Функция C | Детерминированные функции | Указать по функции