Создайте S-функции, которые работают беспрепятственно с Simulink® и продуктами генератора кода при помощи концепции обертки. Вы можете:
Соедините интерфейсом со своими алгоритмами в моделях Simulink путем записи оберток S-функции MEX ().sfunctionMEX
Направьте генератор кода, чтобы вставить ваш алгоритм в сгенерированный код путем создания обертки S-функции TLC ().sfunction.tlc
Создание S-функций при помощи обертки S-функции позволяет вам вставить алгоритмы C/C++ кода в модели Simulink и сгенерированный код с минимальным изменением в вашей исходной функции C/C++. Оберткой S-функции MEX является S-функция, которая вызывает код, который находится в другом модуле.
Используйте обертку S-функции MEX только в версии MATLAB®, в которой вы создали обертку.
Предположим, что у вас есть алгоритм (то есть, функция C) названный my_alg это находится в файле my_alg.c. Можно интегрировать my_alg в модель Simulink путем создания обертки S-функции MEX (например, wrapsfcn.c). Модель Simulink может затем вызвать my_alg от Блока s-function. 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-функции (что вы вводите в диалоговое окно Блока s-function Simulink).
Укажите, что 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Для получения дополнительной информации смотрите Шаблоны для S-функций C (Simulink).
Стандартная программа 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 раздел сгенерированного кода. В примере Обертки S-функции MEX, вызове my_alg встраивается в mdlOutputs разделите как:
*y = my_alg(*uPtrs[0]);
Когда вы создаете обертку S-функции TLC, цель состоит в том, чтобы встроить тот же тип вызова в сгенерированном коде.
Посмотрите на то, как генератор кода выполняет S-функции, которые не встраиваются. Невстроенная S-функция идентифицирована отсутствием файла и существование sfunction.tlc. При генерации кода для невстроенной S-функции генератор кода производит вызов sfunctionMEXmdlOutputs через указатель функции, что, в этом примере, затем вызывает 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-function в вашей модели. Можно значительно уменьшать эти издержки путем создания обертки 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 это встраивает 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-function и генерирует код в C:
%implements "wrapsfcn" "C"
Следующая задача состоит в том, чтобы сообщить генератору кода что стандартный my_alg должен быть объявлен как внешний в сгенерированном wrapper.h файл для любого wrapsfcn Блоки s-function в модели. Сделайте это объявление однажды для всего wrapsfcn Блоки s-function при помощи 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 Кбайт использования памяти.