Создайте S-функции, которые легко работают с продуктами Simulink ® и генераторами кода, используя концепцию обертки. Вы можете:
Сопрягайте алгоритмы в моделях Simulink, записывая оболочки MEX S-функций ().sfunction.mex
Направьте генератор кода для вставки алгоритма в сгенерированный код путем создания оболочки S-функции TLC ().sfunction.tlc
Создание S-функций с помощью оболочки S-функций позволяет вставлять алгоритмы кода C/C + + в модели Simulink и создаваемый код с незначительным изменением исходной функции C/C + + или без него. Оболочка S-функции MEX - это S-функция, вызывающая код, который находится в другом модуле.
Примечание
Используйте оболочку MEX S-функции только в версии MATLAB ®, в которой была создана оболочка.
Предположим, что у вас есть алгоритм (то есть функция C) под названием my_alg который находится в файле my_alg.c. Вы можете интегрировать my_alg в модель Simulink путем создания оболочки MEX S-функции (например, wrapsfcn.c). Модель Simulink может вызвать my_alg из S-функционального блока. S-функция Simulink содержит набор пустых функций, необходимых механизму Simulink для различных целей, связанных с API. Например, хотя только mdlOutputs требования my_alg, механизм вызывает mdlTerminate, даже если эта подпрограмма S-функции не выполняет никаких действий.
Вызов можно встроить в my_alg в сгенерированном коде путем создания оболочки S-функции TLC (например, wrapsfcn.tlc). Можно исключить пустые вызовы функций. Можно избежать накладных расходов при выполнении mdlOutputs и вы можете затем исключить my_alg функция.
S-функции обертки полезны при создании процедурных алгоритмов или при интеграции унаследованного кода в модель Simulink. Если требуется создать код:
Интерпретативный характер (то есть высоко параметризованный режимами работы)
Интенсивная оптимизация (т. е. отсутствие дополнительных тестов для определения режима работы кода)
затем необходимо создать полностью встроенный файл TLC для функции S.
На следующем рисунке показана концепция S-функции обертки.

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

Два файла связаны с wrapsfcn блок: оболочка S-функции и код C/C + +, содержащий алгоритм. Первые три заявления:
Определите имя S-функции (то, что вводится в диалоговом окне Simulink S-Function block).
Укажите, что S-функция использует формат уровня 2.
Предоставление доступа к SimStruct структура данных. SimStruct содержит указатели на данные, используемые при моделировании и генерации кода, и определяет макросы, которые хранят данные в и извлекают данные из SimStruct.
#define S_FUNCTION_NAME wrapsfcn
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
extern real_T my_alg(real_T u); /* Declare my_alg as extern */
/*
* mdlInitializeSizes - initialize the sizes array
*/
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams( S, 0); /*number of input arguments*/
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes( S, 1);
}
/*
* mdlInitializeSampleTimes - indicate that this S-function runs
* at the rate of the source (driving block)
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
/*
* mdlOutputs - compute the outputs by calling my_alg, which
* resides in another module, my_alg.c
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
*y = my_alg(*uPtrs[0]); /* Call my_alg in mdlOutputs */
}
/*
* mdlTerminate - called when the simulation is terminated.
*/
static void mdlTerminate(SimStruct *S)
{
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endifДополнительные сведения см. в разделе Шаблоны для C S-функций.
Подпрограмма S-функций mdlOutputs содержит вызов функции для my_alg, которая является функцией C, содержащей алгоритм, который выполняет S-функция. Для my_alg.c, код:
#ifdef MATLAB_MEX_FILE
#include "tmwtypes.h"
#else
#include "rtwtypes.h"
#endif
real_T my_alg(real_T u)
{
return(u * 2.0);
}Дополнительные сведения см. в разделе Управление зависимостями файлов процесса построения.
Обертка S-функция wrapsfcn требования my_alg, который вычисляет u * 2.0. Построить wrapsfcn.mex, используйте следующую команду:
mex wrapsfcn.c my_alg.c
Оболочка S-функции TLC - это файл TLC, определяющий способ вызова кода генератором кода. Например, можно встроить вызов в my_alg в mdlOutputs раздел сформированного кода. В примере «MEX S-Function Wrapper» вызов my_alg встроен в mdlOutputs раздел как:
*y = my_alg(*uPtrs[0]);
При создании оболочки S-функции TLC целью является внедрение вызова того же типа в сгенерированный код.
Посмотрите, как генератор кода выполняет S-функции, которые не встроены. Неинлинная S-функция идентифицируется отсутствием файла и существование sfunction.tlc. При генерации кода для неинлинной S-функции генератор кода вызывает sfunction.mexmdlOutputs через указатель функции, который в этом примере вызывает my_alg.
Пример обертки содержит одну S-функцию, wrapsfcn.mex. Необходимо скомпилировать и связать дополнительный модуль, my_alg, с сгенерированным кодом. В командной строке MATLAB введите:
set_param('wrapper/S-Function','SFunctionModules','my_alg')
Код, созданный при использовании grt.tlc как системный целевой файл без
wrapsfcn.tlc является:
<Generated code comments for wrapper model with noninlined wrapsfcn S-function>
#include <math.h>
#include <string.h>
#include "wrapper.h"
#include "wrapper.prm"
/* Start the model */
void mdlStart(void)
{
/* (start code not required) */
}
/* Compute block outputs */
void mdlOutputs(int_T tid)
{
/* Sin Block: <Root>/Sin */
rtB.Sin = rtP.Sin.Amplitude *
sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);
/* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
{
/* Noninlined S-functions create a SimStruct object and
* generate a call to S-function routine mdlOutputs
*/
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnOutputs(rts, tid);
}
/* Outport Block: <Root>/Out */
rtY.Out = rtB.S_Function;
}
/* Perform model update */
void mdlUpdate(int_T tid)
{
/* (update code not required) */
}
/* Terminate function */
void mdlTerminate(void)
{
/* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
{
/* Noninlined S-functions require a SimStruct object and
* the call to S-function routine mdlTerminate
*/
SimStruct *rts = ssGetSFunction(rtS, 0);
sfcnTerminate(rts);
}
}
#include "wrapper.reg"
/* [EOF] wrapper.c */ wrapper.reg созданный файл содержит инициализацию SimStruct для блока обертки S-Function. Есть один ребенок SimStruct для каждого S-функционального блока в модели. Можно значительно сократить эти издержки, создав оболочку TLC для S-функции.
Сгенерированный код вызывает функцию S, wrapsfcn.c, в mdlOutputs используя этот код:
SimStruct *rts = ssGetSFunction(rtS, 0); sfcnOutputs(rts, tid);
С этим вызовом связаны вычислительные издержки. Движок Simulink создает SimStruct структура данных для блока S-Function. Генератор кода создает вызов через указатель функции для выполнения mdlOutputs, то mdlOutputs требования my_alg. Встраивая вызов в алгоритм C/C + +,my_alg, вы можете исключить оба SimStruct и вызов дополнительной функции, тем самым повышая эффективность и уменьшая размер генерируемого кода.
Для встраивания S-функции оболочки требуется файл для S-функции. Файл TLC должен содержать вызов функции sfunction.tlcmy_alg. На рисунке показаны взаимосвязи между алгоритмом, S-функцией оболочки и файл.sfunction.tlc

Чтобы встроить вызов в my_alg, поместите вызов функции в файл с тем же именем, что и S-функция (в этом примере sfunction.tlcwrapsfcn.tlc). Компилятор целевого языка переопределяет используемый по умолчанию метод размещения вызовов S-функции в сгенерированном коде.
Этот код является TLC-файлом wrapsfcn.tlc что inlines wrapsfcn.c:
%% File : wrapsfcn.tlc %% Abstract: %% Example inlined tlc file for S-function wrapsfcn.c %% %implements "wrapsfcn" "C" %% Function: BlockTypeSetup ==================================================== %% Abstract: %% Create function prototype in model.h as: %% "extern real_T my_alg(real_T u);" %% %function BlockTypeSetup(block, system) void %openfile buffer extern real_T my_alg(real_T u); /* This line is placed in wrapper.h */ %closefile buffer %<LibCacheFunctionPrototype(buffer)> %endfunction %% BlockTypeSetup %% Function: Outputs =========================================================== %% Abstract: %% y = my_alg( u ); %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %assign u = LibBlockInputSignal(0, "", "", 0) %assign y = LibBlockOutputSignal(0, "", "", 0) %% PROVIDE THE CALLING STATEMENT FOR "algorithm" %% The following line is expanded and placed in mdlOutputs within wrapper.c %<y> = my_alg(%<u>); %endfunction %% Outputs
Первый раздел этого кода включает в себя wrapsfcn S-Функциональный блок и генерирует код в C:
%implements "wrapsfcn" "C"
Следующая задача - сообщить генератору кода, что подпрограмма my_alg должен быть объявлен как внешний в сгенерированном wrapper.h файл для любого wrapsfcn S - функциональные блоки в модели. Сделать это объявление один раз для всех wrapsfcn S-функциональные блоки с помощью BlockTypeSetup функция. В этой функции компилятор целевого языка используется для создания буфера и кэширования my_alg как extern в wrapper.h сгенерированный файл заголовка.
Последним шагом является включение вызова функции. my_alg. Outputs функция встраивает вызов. В этой функции осуществляется доступ к входу и выходу блока и выполняется прямой вызов my_alg. Вызов встроен в wrapper.c.
Код, генерируемый при встраивании S-функции оболочки, аналогичен коду, создаваемому по умолчанию. mdlTerminate функция не содержит вызова пустой функции и mdlOutputs функция теперь напрямую вызывает my_alg.
void mdlOutputs(int_T tid)
{
/* Sin Block: <Root>/Sin */
rtB.Sin = rtP.Sin.Amplitude *
sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);
/* S-Function Block: <Root>/S-Function */
rtB.S_Function = my_alg(rtB.Sin); /* Inlined call to my_alg */
/* Outport Block: <Root>/Out */
rtY.Out = rtB.S_Function;
}wrapper.reg не создает дочерний элемент SimStruct для S-функции, поскольку генерируемый код вызывает my_alg непосредственно, исключая использование более 1 КБ памяти.