cmex s函数允许您调用Simulink中现有的C代码万博1manbetx®模型。例如,考虑一个简单的C函数doubleIt.c
输出的值是函数输入值的两倍。
{return(u * 2.0);}
你可以创建一个s函数来调用doubleIt.c
通过:
编写一个包装器s函数。使用这种方法,您可以手工编写一个新的C s函数和相关的TLC文件。这种方法需要对C函数的结构有最深入的了解。
使用S-Function构造器块。使用此方法,您可以将S-function的特征输入到块对话框中。这种方法不需要任何关于编写s函数的知识。但是,对s函数的结构有基本的了解可以使s函数构建器对话框更容易使用。
使用遗留代码工具。使用这个命令行方法,可以在MATLAB的数据结构中定义s函数的特征®工作区。这种方法对s函数的知识要求最少。
您还可以使用MATLAB函数块从Simulink模型调用外部C代码。万博1manbetx有关更多信息,请参见用C代码集成MATLAB函数块。
下面几节将描述如何创建用于Simulink模拟的s函数万博1manbetx和万博1manbetx仿真软件编码器™代码生成,使用前面的三种方法。该模型sfcndemo_choosing_sfun
包含使用这些s函数的块。复制这个模型和文件doubleIt.c
和doubleIt.h
从文件夹中docroot
/工具/模型/ s万博1manbetxfg /例子
如果您计划逐步遍历示例,请将其放入您的工作文件夹。
的功能wrapsfcn.c
调用遗留函数doubleIt.c
在其mdlOutputs
方法。保存wrapsfcn.c
如果您计划编译S-function以在示例模型中运行,则将该文件放入您的工作文件夹中sfcndemo_choosing_sfun
。
要将遗留代码合并到s函数中,wrapsfcn.c
首先声明doubleIt.c
用以下文字表示:
extern real_T doubleIt(real_T u);
声明之后,s函数就可以使用了doubleIt.c
在其mdlOutputs
方法。例如:
/ *功能:mdlOutputs = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = *文摘:*调用doubleIt.c函数多个输入2。{InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);real_T *y = ssGetOutputPortRealSignal(S,0);* y = doubleIt (* uPtrs [0]);}
来编译wrapsfcn.c
S-function,运行以下命令墨西哥人
命令。确保doubleIt.c
文件在您的工作文件夹中。
墨西哥人wrapsfcn.c doubleIt.c
方法生成s函数的代码万博1manbetx仿真软件编码器代码生成器,需要编写一个目标语言编译器(TLC)文件。以下TLC文件wrapsfcn.tlc
使用BlockTypeSetup
要为其声明函数原型的函数doubleIt.c
。薄层色谱文件的输出
函数然后告诉万博1manbetx仿真软件编码器代码生成器如何内联调用doubleIt.c
。例如:
实现"wrapsfcn" "C" %%文件:wrapsfcn。%%抽象:%%在model.h中创建函数原型,作为:%% "extern double double leit (double u);"提供一行代码作为函数原型extern double double leit (double u);% closefile缓冲% < LibCacheFunctionPrototype(缓冲)> % % endfunction % % BlockTypeSetup % %功能:输出= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = % %文摘:% %调用遗留功能:y = doubleIt (u);%% %函数输出(block, system)输出/* %block: % */ %assign u = LibBlockInputSignal(0, "", "", ", ", 0) %assign y = LibBlockOutputSignal(0, "", ", ", ", 0) %%提供对"doubleIt" % = doubleIt(%)的调用语句% endfunction % %输出
有关TLC的更多信息,请参见目标语言编译器简介(万博1manbetx仿真软件编码器)。
S-Function构建器自动创建包含遗留代码的S-Function和TLC文件。对于本例,除了doubleIt.c
,您需要头文件doubleIt.h
这声明doubleIt.c
函数格式如下:
extern real_T doubleIt;
中的S-Function构建器块sfcndemo_choosing_sfun
演示如何配置块对话框来调用遗留函数doubleIt.c
。在S-Function Builder块对话框中:
的功能名称字段参数窗格定义名称builder_wrapsfcn
对于生成的s函数。
的数据属性窗格将输入和输出端口命名为三机一体
和着干活
,分别。
的库窗格提供遗留代码的接口。
的图书馆/对象/源文件字段包含源文件名称doubleIt.c
。
的包括字段包含以下行来包含声明遗留函数的头文件:
# include < doubleIt.h >
的输出窗格通过以下行调用遗留函数:
/*调用将输入乘以2 */ *out1 = doubleIt(*in1)的函数;
的建立信息窗格中选择生成包装器薄层色谱选择。
当你点击构建, S-Function构建器生成三个文件。
文件名称 | 描述 |
---|---|
builder_wrapsfcn.c |
主要的功能。 |
builder_wrapsfcn_wrapper.c |
控件中输入的代码包含单独函数的包装文件输出,连续的衍生品,离散更新S-Function构建器的窗格。 |
builder_wrapsfcn.tlc |
函数的TLC文件。 |
的builder_wrapsfcn.c
文件遵循标准格式:
文件以一组#定义
包含来自S-Function构建器的信息的语句。例如,下面几行定义了第一个输入端口:
#define INPUT_0_DTYPE real_T #define INPUT_0_COMPLEX COMPLEX_NO #define IN_0_FRAME_BASED FRAME_NO #define IN_0_DIMS 1- d #define INPUT_0_FEEDTHROUGH 1
然后,该文件声明在builder_wrapsfcn_wrapper.c
文件。对象只需要一个包装器函数输出代码。
extern void builder_wrapsfcn_Outputs_wrapper(const real_T *in1, real_T *out1)
根据这些定义和声明,该文件包含S-function方法,例如mdlInitializeSizes
,用于初始化s函数的输入端口、输出端口和参数。看到流程视图用于在S-function初始化阶段调用的方法列表。
该文件mdlOutputs
方法调用的builder_wrapsfcn_wrapper.c
函数。该方法使用输入和输出名称三机一体
和着干活
的定义数据属性调用包装器函数时。例如:
/ *功能:mdlOutputs = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * * /静态孔隙mdlOutputs (SimStruct *年代,int_T tid) {const real_T *三机= (const real_T *) ssGetInputPortSignal (S, 0);ssGetOutputPortRealSignal(S,0);builder_wrapsfcn_Outputs_wrapper (in1,着干活);}
该文件builder_wrapsfcn.c
以必需的mdlTerminate
方法。
包装器函数builder_wrapsfcn_wrapper.c
有三个部分:
的包含文件
部分包括doubleIt.h
文件,连同标准的s -函数头文件:
if defined(MATLAB_MEX_FILE) # Include "tmwtypes "h simstruc_types # include。其他包括rtwtypes。h" #endif /* %%%-SFUNWIZ_wrapper_includes_Changes_BEGIN——在这里编辑为_END */ #include
的外部引用
部分包含来自外部引用声明场的库窗格。本示例不使用此部分。
的输出函数
section声明函数builder_wrapfcn_Outputs_wrapper
,其中包含在S-Function Builder块对话框中输入的代码输出面板:
/* *输出函数* */ void builder_wrapfcn_Outputs_wrapper(const real_T *in1, real_T *out1) {/* %%-SFUNWIZ_wrapper_Outputs_Changes_BEGIN——此处编辑为_END */ /* Call函数,该函数将输入乘以2 */ *out1 = doubleIt(*in1);/* %%%-SFUNWIZ_wrapper_Outputs_Changes_END——此处编辑为_BEGIN */}
与手写的s -函数相比,S-function构建器通过包装器文件将对遗留C函数的调用降低了一层builder_wrapsfcn_wrapper.c
。
薄层色谱文件builder_wrapsfcn.tlc
由S-Function构建器生成的代码类似于之前的手写版本。中声明遗留函数BlockTypeSetup
调用它输出
方法。
%实现builder_wrapsfcn "C" %%函数:块typesetup ==================================== ========================= %% %目的:%%在生成的代码中为包装器函数设置外部引用。%% %function BlockTypeSetup(block, system)输出%openfile extern void builder_wrapsfcn_Outputs_wrapper(const real_T *in1, real_T *out1);% closefile走读生% < LibCacheExtern(外来的)> % % % endfunction % %功能:输出= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = % % % %目的:% % mdlOutputs函数代码生成规则。% % %函数输出(块,系统)输出/ * s函数“builder_wrapsfcn_wrapper”块:% <名称> * / %分配pu0 = LibBlockInputSignalAddr(0,”“、”“0)%分配py0 = LibBlockOutputSignalAddr(0,”“、”“0)%分配py_width = LibBlockOutputSignalWidth(0) %分配pu_width = LibBlockInputSignalWidth (0) builder_wrapsfcn_Outputs_wrapper (% < pu0 >, % < py0 >);% % % endfunction
一节使用遗留代码工具将C函数集成到Simulink模型中万博1manbetx在“用C编写s函数”中展示了如何使用遗留代码工具来创建一个合并的s函数doubleIt.c
。对于执行该示例中的步骤的脚本,复制该文件lct_wrapsfcn.m
到您的工作文件夹。确保doubleIt.c
和doubleIt.h
文件在您的工作文件夹中,然后通过键入运行脚本lct_wrapsfcn
在MATLAB命令提示符下。该脚本创建并编译s函数legacy_wrapsfcn.c
并创建TLC文件legacy_wrapsfcn.tlc
通过以下命令。
%创建数据结构def = legacy_code('initialize');%填充数据结构def.SourceFiles = {'double .c'};def.HeaderFiles = {' doubleIt.h '};def.SFunctionName =“legacy_wrapsfcn”;def.OutputFcnSpec = '双y1 =双u1 ';def.SampleTime = (1,0);%生成s函数legacy_code('sfcn_cmex_generate', def);%编译mex文件legacy_code(' Compile ', def);%生成一个tlc文件legacy_code('sfcn_tlc_generate', def);
的功能legacy_wrapsfcn.c
由遗留代码工具生成的doubleIt.h
头文件。的mdlOutputs
方法直接调用doubleIt.c
函数,如下:
获取参数/输入/输出/DWork/size信息*/ real_T *u1 = (real_T *) ssGetInputPortSignal(S, 0);real_T *y1 = (real_T *) ssGetOutputPortSignal(S, 0);/* *调用遗留代码函数*/ *y1 = doubleIt(*u1);}
由遗留代码工具生成的s函数与由s函数构建器生成的s函数的区别如下:
由S-function构建器生成的s -函数调用遗留函数doubleIt.c
通过包装器函数builder_wrapsfcn_wrapper.c
。由遗留代码工具生成的S-function直接调用doubleIt.c
从它的mdlOutputs
方法。
构造器使用输入到的输入和输出名称数据属性窗格,允许您在s -函数中自定义这些名称。遗留代码工具使用默认名称y
和u
分别为输出和输入。在使用遗留代码工具时,不能指定要在生成的s -函数中使用的自定义名称。
默认情况下,S-Function构建器和遗留代码工具都指定了一个继承的示例时间。但是,S-Function构建器使用的偏移时间为0.0
而遗留代码工具指定偏移时间在较小的时间步骤中固定。
薄层色谱文件legacy_wrapsfcn.tlc
万博1manbetx通过定义支持表达式折叠BlockInstanceSetup
和BlockOutputSignal
功能。TLC文件还包含BlockTypeSetup
要为其声明函数原型的函数doubleIt.c
和一个输出
函数来告知万博1manbetx仿真软件编码器代码生成器如何内联调用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 = "块输出端口索引不支持:%" %endi万博1manbetxf %默认%assign errTxt = "不支持返回类型:% " % %endswitch