我在C中编写了一个Simulink S函数(Level 2)。生成的块有一个输出和一个参数。此参数存储在变量中,该变量在设置块后立即在文件范围定义:
#define NUM_PARAMS 1
#define NUM_INPORTS 0
#define NUM_OUTPORTS 1
unsigned short int MASK_INDEX;
我在mdlInitializeSizes中分配它,并对其值进行一些操作:
static void mdlInitializeSizes(SimStruct *S) {
// Check Parameters
ssSetNumSFcnParams(S, NUM_PARAMS);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
MASK_INDEX = *mxGetPr(ssGetSFcnParam(S, 0));
(...) operations
}
我的问题是,变量MASK_INDEX似乎是全局的,并且在相同类型的所有块之间共享。因此,它对所有块保持相同的值。
作为一种解决方法,我每次都重新加载它,并重新执行操作,例如:
static void mdlOutputs(SimStruct *S, int_T tid) {
MASK_INDEX = *mxGetPr(ssGetSFcnParam(S, 0));
(...) operations
}
如何获得真正的“局部变量”,这样我每次都不必重复所有这些?
答案 0 :(得分:2)
您还没有提到您声明MASK_INDEX
的位置,但是根据您的说明,它听起来像是在文件范围内。如果是,那么是的,这个变量将在所有实例之间共享。这不是以任何方式与S-Functions隔离的,它是大多数(如果不是全部)平台上的共享库的行为方式。共享库的单个实例将由应用程序加载,在本例中为MATLAB;因此,只有一个全局变量副本。
最简单的选择是每次要访问参数时都使用ssGetSFcnParam
。如果您深入研究这些S-Function宏,他们只是访问SimStruct
的字段,因此重复访问不太可能导致性能下降。我甚至已经看到用于包装常用用例的宏,例如你的用例。
如果你真的想要缓存对话框参数,最简单的可能就是使用ssSetUserData
。声明包含struct
成员的MASK_INDEX
(您不 使用struct
但这种方法更具扩展性。使用mxMalloc
中的mdlStart
动态分配实例,并将其分配给块的用户数据。请务必在ssSetOptions
的{{1}}来电中设置SS_OPTION_CALL_TERMINATE_ON_EXIT
。然后使用mdlInitializeSizes
和mdlTerminate
定义struct
函数,在其中您将访问已分配的ssGetUserData
。现在,您可以使用mxFree
访问struct
中的mdlOutputs
个成员。
还有其他更高级的选项,例如work vectors,可能是PWork vector。
另一个选项,如果您的参数是可调参数,则使用runtime parameters,它允许您缓存并可选地转换块的对话框参数。
在您的情况下,我只是坚持在ssGetUserData
内每次使用ssGetSFcnParam
。