C MEX s -函数允许您在Simulink中调用现有的C代码金宝app®模型。例如,考虑简单的C函数doubleIt.c
输出的值是函数输入值的两倍。
double doubleIt(double u) {return(u * 2.0);}
你可以创建一个s函数来调用doubleIt.c
通过:
您还可以使用MATLAB函数块从Simulink模型调用外部C代码。金宝app有关更多信息,请参见利用MATLAB函数块集成C代码.
以下部分描述如何创建在Simulink仿真中使用的s -函数金宝app和金宝app仿真软件编码器™代码生成,使用前三种方法。示例模型包含使用这些s -函数的块。如果您计划创建模型,请复制文件doubleIt.c
和加倍
从文件夹中docroot/toolbox/金宝appsimulink/examples
放入您的工作文件夹。
的功能wrapsfcn.c
调用遗留函数doubleIt.c
在其mdlOutputs
方法拯救wrapsfcn.c
如果计划创建示例模型,请将文件保存到工作文件夹中。
要将遗留代码合并到S函数中,wrapsfcn.c
首先声明doubleIt.c
用下面的行:
extern real_T doubleIt(real_T u);
一旦声明,S函数就可以使用doubleIt.c
在其mdlOutputs
方法。例如:
/*函数:mdlOutputs====================================================*摘要:*调用doubleIt.c函数将输入乘以2。*/静态void mdlOutputs(SimStruct*S,int tid){InputRealPtrsType uPtrs=ssGetInputPortRealSignalPtrs(S,0);real_T*y=ssgetoutputprealsignal(S,0);*y=doubleIt(*uPtrs[0])}
来编译wrapsfcn.c
s函数,运行以下命令墨西哥人
命令。确保doubleIt.c
文件在您的工作文件夹中。
墨西哥人wrapsfcn.c doubleIt.c
使用金宝appSimulink编码器代码生成器,您需要编写一个目标语言编译器(TLC)文件wrapsfcn.tlc
使用BlockTypeSetup
函数来声明函数原型doubleIt.c
.TLC文件输出
函数告诉金宝appSimulink编码器代码生成器如何内联调用doubleIt.c
.例如:
%%实现"wrapsfcn" "C" %% File: wrapsfcn. "在model.h中创建函数原型为:%% "extern double doubleIt(double u);"%% %function BlockTypeSetup(block, system) void %openfile buffer %%提供一行代码作为函数原型extern double doubleIt(double u);% closefile缓冲% < LibCacheFunctionPrototype(缓冲)> % % endfunction % % BlockTypeSetup % %功能:输出 ======================================= %% 文摘:% %调用遗留功能:y = doubleIt (u);%% %function Outputs(block, system) Output /* %block: % */ %assign u = LibBlockInputSignal(0, "", "", 0) %assign y = libblocoutputsignal (0, "", "", 0) %% PROVIDE THE CALLING STATEMENT FOR "doubleIt" % = doubleIt(%);% endfunction % %输出
有关TLC的更多信息,请参阅目标语言编译器基础(金宝app仿真软件编码器).
S-Function Builder自动创建包含遗留代码的S-Function和TLC文件。对于本例,除了doubleIt.c
,则需要头文件加倍
这声明doubleIt.c
函数格式,如下所示:
extern real_T doubleIt(real_T in1);
使用S-Function Builder块配置块对话框来调用遗留函数doubleIt.c
.在S-Function Builder块对话框中:
的功能名称字段参数窗格定义名称建筑商
对于生成的s函数。
的数据属性窗格将输入和输出端口命名为内
和着干活
,分别。
的图书馆窗格提供到遗留代码的接口。
的库/对象/源文件字段包含源文件名doubleIt.c
.
的包括字段包含以下行,以包含声明遗留函数的头文件:
#包括
的输出窗格使用以下行调用旧函数:
/*调用函数,将输入乘以2 */ *out1 = doubleIt(*in1);
的建立信息窗格中选择生成包装TLC选择。
当你点击建筑,S函数生成器生成三个文件。
文件名称 | 描述 |
---|---|
builder_wrapsfcn.c |
主要的功能。 |
builder_wrapsfcn_wrapper.c |
控件中输入的代码包含独立函数的包装器文件输出,连续的衍生品和离散更新窗格的S-Function Builder。 |
builder_wrapsfcn.tlc |
s函数的TLC文件。 |
的builder_wrapsfcn.c
文件遵循标准格式:
该文件以一组#定义
包含S函数生成器信息的语句。例如,以下行定义了第一个输入端口:
#定义数字输入1/*输入端口0*/#定义输入端口0名称1#定义输入0宽度1#定义输入DIMS 0列1#定义输入0数据类型实数#定义输入0复杂复数#定义基于帧的帧#定义输入0 DIMS 1-D#定义输入1
接下来,该文件声明在builder_wrapsfcn_wrapper.c
文件。的示例只需要一个包装器函数输出代码。
extern void builder_wrapsfcn_Outputs_wrapper(const real_T *in1, real_T *out1);
在这些定义和声明之后,该文件包含S函数方法,例如中密度
,初始化S函数的输入端口、输出端口和参数。看见流程视图获取在s函数初始化阶段调用的方法列表。
的mdlOutputs
方法调用builder_wrapsfcn_wrapper.c
函数。该方法使用输入和输出名称内
和着干活
的定义数据属性窗格,调用包装器函数时。例如:
/*函数:mdlOutputs================================================**/静态无效mdlOutputs(SimStruct*S,int_T tid){const real_T*in1=(const real_T*)ssGetInputPortSignal(S,0);real_T*out1=(real_T*)ssGetOutputPortRealSignal(S,0);builder_wrapsfcn输出包装器(in1,0)}
该文件builder_wrapsfcn.c
以所需的内容结束mdlTerminate
方法。
包装函数builder_wrapsfcn_wrapper.c
分为三个部分:
的包括文件
部分包括加倍
文件,连同标准的S-function头文件:
/ * *包含文件* * #如果定义(MATLAB_MEX_FILE) # Include“tmwtypes.h”#包括其他“simstruc_types.h”# #包括“rtwtypes.h”# endif / * % % % -SFUNWIZ_wrapper_includes_Changes_BEGIN——编辑这里_END * / # Include < math.h > # Include < doubleIt.h > / * % % % -SFUNWIZ_wrapper_includes_Changes_END——编辑_BEGIN * /
的外部参照
节包含来自外部引用声明场的图书馆窗格。此示例不使用此部分。
的输出函数
节声明函数builder_wrapfcn_Outputs_wrapper
,它包含在S-Function Builder块对话框中输入的代码输出窗格:
/* *输出函数* */ void builder_wrapfcn_Outputs_wrapper(const real_T *in1, real_T *out1) {/* %%%-SFUNWIZ_wrapper_Outputs_Changes_BEGIN——EDIT HERE TO _END */ /*调用函数,将输入乘以2 */ *out1 = doubleIt(*in1);/* %%%-SFUNWIZ_wrapper_Outputs_Changes_END——EDIT HERE TO _BEGIN */}
请注意
与手写S函数相比,S函数生成器通过包装文件将对传统C函数的调用降低了一个附加级别builder_wrapsfcn_wrapper.c
.
TLC文件builder_wrapsfcn.tlc
生成的S-Function Builder类似于以前的手写版本。文件中声明了遗留函数BlockTypeSetup
并在输出
方法。
%%在%%生成的代码中为包装器函数设置外部引用。%% %函数BlockTypeSetup(block, system)输出%openfile externs extern void builder_wrapsfcn_Outputs_wrapper(const real_T *in1, real_T *out1);% closefile走读生% < LibCacheExtern(外来的)> % % % endfunction % %功能:输出 =========================================== %% %% 目的:% % mdlOutputs函数代码生成规则。/* S-Function "builder_wrapsfcn_wrapper" block:%*/ %assign pu0 = LibBlockInputSignalAddr(0, "", "", 0) %assign py0 = libblocoutputsignaladdr (0, "", "", 0) %assign py_width = LibBlockInputSignalWidth(0) %assign pu_width = LibBlockInputSignalWidth(0) builder_wrapsfcn_Outputs_wrapper(% , % );% % % endfunction
部门使用遗留代码工具将C函数集成到Simulink模型中金宝app在“用C编写S-Functions”中展示了如何使用遗留代码工具创建一个合并的S-functiondoubleIt.c
.对于执行该示例中的步骤的脚本,复制该文件lct_wrapsfcn.m
到您的工作文件夹。确保doubleIt.c
和加倍
文件位于您的工作文件夹中,然后通过键入来运行脚本lct_wrapsfcn
在MATLAB命令提示符处。该脚本创建并编译s函数legacy_wrapsfcn.c
并创建TLC文件遗产_wrapsfcn.tlc
通过以下命令。
创建数据结构def = legacy_code('initialize');%填充数据结构def.SourceFiles = {'doubleIt.c'};def.HeaderFiles = {' doubleIt.h '};def.SFunctionName =“legacy_wrapsfcn”;def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';def.SampleTime = (1,0);%生成S-function legacy_code('sfcn_cmex_generate', def);%编译MEX-file legacy_code(' Compile ', def);%生成一个tlc文件legacy_code('sfcn_tlc_generate', def);
的功能legacy_wrapsfcn.c
由遗留代码工具生成的加倍
头文件。的mdlOutputs
方法然后直接调用doubleIt.c
功能如下:
static void mdlOutputs(SimStruct *S, int_T tid) {/* * Get access to Parameter/Input/Output/DWork/size information */ real_T *u1 = (real_T *) ssGetInputPortSignal(S, 0);real_T *y1 = (real_T *) ssGetOutputPortSignal(S, 0); / /输出信号/* *调用遗留代码函数*/ *y1 = doubleIt(*u1);}
Legacy Code Tool生成的s函数与S-function Builder生成的s函数的区别如下:
由S函数生成器生成的S函数调用旧函数doubleIt.c
通过包装器函数builder_wrapsfcn_wrapper.c
.传统代码工具生成的S函数直接调用doubleIt.c
从它的mdlOutputs
方法。
S-Function Builder使用输入和输出名称数据属性窗格,允许您在s -函数中自定义这些名称。遗留代码工具使用默认名称y
和u
分别为输出和输入。当使用遗留代码工具时,您不能指定要在生成的s -函数中使用的自定义名称。
默认情况下,S-Function Builder和遗留代码工具都指定继承的示例时间。但是,S-Function Builder使用的偏移时间为0.0
而传统代码工具指定偏移时间固定在较小的时间步长中。
TLC文件遗产_wrapsfcn.tlc
金宝app通过定义支持表达式折叠BlockInstanceSetup
和BlockOutputSignal
功能。TLC文件还包含一个BlockTypeSetup
函数来声明函数原型doubleIt.c
和一个输出
函数来告诉金宝appSimulink编码器代码生成器如何内联调用doubleIt.c
.:
% %功能:BlockTypeSetup =============================================== %% % 函数BlockTypeSetup(块,系统)无效% % % %目标语言必须C %如果::GenCPP = = 1% < LibReportFatalError(“这功能由遗留代码生成工具必须只使用C目标语言”)> % endif % < LibAddToCommonIncludes (doubleIt.h) > % < LibAddToModelSources (doubleIt) > % % % endfunction % %功能:BlockInstanceSetup =========================================== %% % 函数BlockInstanceSetup(块、系统)无效% % % < LibBlockSetIsExpressionCompliant(块)> % % % endfunction % %功能:输出 ====================================================== %% % 函数输出(块、系统)输出% % % ! LibBlockOutputSignalIsExpr(0) %分配u1_val = LibBlockInputSignal (0 , "", "", 0) %分配y1_val = LibBlockOutputSignal (0 , "", "", 0) % % % < y1_val = doubleIt (% < u1_val >);%endif %% endfunction %%BlockOutputSignal ============================================ %% % 函数BlockOutputSignal(块,系统、portIdx ucv,液位控制阀,idx, retType)无效% % %分配u1_val = LibBlockInputSignal (0 , "", "", 0) %分配y1_val = LibBlockOutputSignal (0 , "", "", 0) % % %开关retType %例“信号”%如果portIdx = = 0%的回报”doubleIt (% < u1_val >)”%else %assign errTxt = "Block output port index not 金宝appsupported: %" %endif %default %assign errTxt = "Unsupported return type: % " % %endswitch %% %endfunction .