在多个 c mex s-function 之间共享数据
Share data between multiple c mex s-functions
我正在实现几个 C 函数。它们必须依赖于相同的指针和变量,与当前的 s-function 无关。
基本上我想在一个 "setup" s-function(在 mdlInitialize 内部)中实例化所有变量和指针,然后能够在它们的 mdlOutputs 函数中使用这些变量和不同 s-function 中的指针。每个 s-function 都将用 c 编写。
我在 mathworks 帮助中找不到任何有用的提示。你有什么主意吗?谢谢。
有几种方法可以做到这一点,尽管其中 none 显然是最好的 方法。
一种方法是在 dll 中定义所有内容,并由每个 S-Function 加载。问题 How to share a C struct among C S-Functions?.
中对此进行了概述
另一种(也是我的首选)方法是创建自定义数据类型,它是一个包含所有共享数据的 C 结构,并将其作为模型中 S-Function 之间的信号传递。文档 Configure Custom Data Types.
的 Using Opaque Data Types in C S-Functions
部分对此进行了概述
该文档显示了在创建自定义结构的 S-Function 中需要完成的各种(相对简单的)事情。在这个 S-Functions MdlOutputs
方法中,自定义结构将以通常的方式作为块的输出。例如,如果包含您的数据的自定义结构定义为,
typedef struct{
real_T sig0;
real_T sig1;
}myStruct;
然后在 mdlInitializeSizes
你需要类似的东西,
myStruct tmp;
/* Register the user-defined data types */
id = ssRegisterDataType(S, "customDataType");
if(id == INVALID_DTYPE_ID) return;
/* Set the size of the user-defined data type */
status = ssSetDataTypeSize(S, id, sizeof(tmp));
if(status == 0) return;
/* Set the zero representation */
tmp.sig0 = 0;
tmp.sig1 = 0;
status = ssSetDataTypeZero(S, id, &tmp);
为了将其作为信号输出,在 mdlOutputs
方法中,您需要类似
myStruct *pY0 = (myStruct *)ssGetOutputPortSignal(S, 0);
pY0[0].sig0 = 'value of this param';
pY0[0].sig1 = 'value of this param';
然后在任何需要使用此信号的 S-Function 的 mdlInitializeSizes
中
DTypeId id;
id = ssRegisterDataType(S, "customDataType");
if(id == INVALID_DTYPE_ID) return;
然后您可以使用
在任何其他方法中访问自定义结构
myStruct **uPtrs = (myStruct **) ssGetInputPortSignalPtrs(S,0);
然后以通常的方式访问结构的元素,
firstVar = uPtrs[0]->sig0;
secondVar = uPtrs[0]->sig1;
这种方法的主要缺点是模型不能用于代码生成(使用 Simulink Coder)。
在 生成的代码 中,在 S-Function 之间共享数据的最简单方法就是通过全局变量传递它,以防您的 S-Function 是非内联的。
因为您在使用已定义的变量时遇到错误,我想您是在目标平台上编译生成的代码。在这种情况下,它是由重复定义引起的——全局变量必须仅在 "setup" S-函数中定义,并在所有其他 S-函数中使用 extern 关键字声明函数(这只是目标中的普通 C)。
当 S-Function 在 Simulink 环境中使用 mex 编译时,它不能静态地 linked 到其他 S-Function。虽然可以使用相同的外部 C 源文件 link 多个 S-Function,但在 Simulink 中,您可能会获得为每个 S-funciton 独立创建的相同数据的多个实例。因为 S-Function 是在 Simulink 环境中独立编译和编辑的,所以在每个 S-Function 中定义公共全局变量没有意义——你不能 extern 它们,因为它们不会为 linker 定义(由 mex 调用)。
在目标上 linking 全局变量的明显缺点是您不能使用 Simulink 环境来调试依赖于共享数据的功能。但如果它不是主要功能(例如一些补充日志记录),它可以有条件地包含在您的 S-Function 中的 RT 标志中,以仅出现在生成的代码中,从而允许验证 Simulink 中的主要功能。
我正在实现几个 C 函数。它们必须依赖于相同的指针和变量,与当前的 s-function 无关。
基本上我想在一个 "setup" s-function(在 mdlInitialize 内部)中实例化所有变量和指针,然后能够在它们的 mdlOutputs 函数中使用这些变量和不同 s-function 中的指针。每个 s-function 都将用 c 编写。
我在 mathworks 帮助中找不到任何有用的提示。你有什么主意吗?谢谢。
有几种方法可以做到这一点,尽管其中 none 显然是最好的 方法。
一种方法是在 dll 中定义所有内容,并由每个 S-Function 加载。问题 How to share a C struct among C S-Functions?.
中对此进行了概述另一种(也是我的首选)方法是创建自定义数据类型,它是一个包含所有共享数据的 C 结构,并将其作为模型中 S-Function 之间的信号传递。文档 Configure Custom Data Types.
的Using Opaque Data Types in C S-Functions
部分对此进行了概述
该文档显示了在创建自定义结构的 S-Function 中需要完成的各种(相对简单的)事情。在这个 S-Functions MdlOutputs
方法中,自定义结构将以通常的方式作为块的输出。例如,如果包含您的数据的自定义结构定义为,
typedef struct{
real_T sig0;
real_T sig1;
}myStruct;
然后在 mdlInitializeSizes
你需要类似的东西,
myStruct tmp;
/* Register the user-defined data types */
id = ssRegisterDataType(S, "customDataType");
if(id == INVALID_DTYPE_ID) return;
/* Set the size of the user-defined data type */
status = ssSetDataTypeSize(S, id, sizeof(tmp));
if(status == 0) return;
/* Set the zero representation */
tmp.sig0 = 0;
tmp.sig1 = 0;
status = ssSetDataTypeZero(S, id, &tmp);
为了将其作为信号输出,在 mdlOutputs
方法中,您需要类似
myStruct *pY0 = (myStruct *)ssGetOutputPortSignal(S, 0);
pY0[0].sig0 = 'value of this param';
pY0[0].sig1 = 'value of this param';
然后在任何需要使用此信号的 S-Function 的 mdlInitializeSizes
中
DTypeId id;
id = ssRegisterDataType(S, "customDataType");
if(id == INVALID_DTYPE_ID) return;
然后您可以使用
在任何其他方法中访问自定义结构myStruct **uPtrs = (myStruct **) ssGetInputPortSignalPtrs(S,0);
然后以通常的方式访问结构的元素,
firstVar = uPtrs[0]->sig0;
secondVar = uPtrs[0]->sig1;
这种方法的主要缺点是模型不能用于代码生成(使用 Simulink Coder)。
在 生成的代码 中,在 S-Function 之间共享数据的最简单方法就是通过全局变量传递它,以防您的 S-Function 是非内联的。
因为您在使用已定义的变量时遇到错误,我想您是在目标平台上编译生成的代码。在这种情况下,它是由重复定义引起的——全局变量必须仅在 "setup" S-函数中定义,并在所有其他 S-函数中使用 extern 关键字声明函数(这只是目标中的普通 C)。
当 S-Function 在 Simulink 环境中使用 mex 编译时,它不能静态地 linked 到其他 S-Function。虽然可以使用相同的外部 C 源文件 link 多个 S-Function,但在 Simulink 中,您可能会获得为每个 S-funciton 独立创建的相同数据的多个实例。因为 S-Function 是在 Simulink 环境中独立编译和编辑的,所以在每个 S-Function 中定义公共全局变量没有意义——你不能 extern 它们,因为它们不会为 linker 定义(由 mex 调用)。
在目标上 linking 全局变量的明显缺点是您不能使用 Simulink 环境来调试依赖于共享数据的功能。但如果它不是主要功能(例如一些补充日志记录),它可以有条件地包含在您的 S-Function 中的 RT 标志中,以仅出现在生成的代码中,从而允许验证 Simulink 中的主要功能。