文档

s -函数合并了遗留的C代码

概述

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.cdoubleIt.h从文件夹中docroot/工具/模型/ s万博1manbetxfg /例子如果您计划逐步遍历示例,请将其放入您的工作文件夹。

使用手写的s -函数合并遗留代码

的功能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.cS-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构建器自动创建包含遗留代码的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  # include < doubleIt。h> /* %%%-SFUNWIZ_wrapper_includes_Changes_END——在这里编辑为_BEGIN */
  • 外部引用部分包含来自外部引用声明场的窗格。本示例不使用此部分。

  • 输出函数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.cdoubleIt.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 -函数中自定义这些名称。遗留代码工具使用默认名称yu分别为输出和输入。在使用遗留代码工具时,不能指定要在生成的s -函数中使用的自定义名称。

  • 默认情况下,S-Function构建器和遗留代码工具都指定了一个继承的示例时间。但是,S-Function构建器使用的偏移时间为0.0而遗留代码工具指定偏移时间在较小的时间步骤中固定。

薄层色谱文件legacy_wrapsfcn.tlc万博1manbetx通过定义支持表达式折叠BlockInstanceSetupBlockOutputSignal功能。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
这个话题有用吗?