Share data between multiple c mex s-functions

对着背影说爱祢 提交于 2019-12-13 20:30:42

问题


I am implementing several c s-functions. They have to rely on the same pointers and variables, inedependet of the current s-function.

Basically I want to instantiate all variabels and pointers in one "setup" s-function (inside mdlInitialize) and then be able to use these variables an pointers in different s-functions in their mdlOutputs function. Every s-function will be written in c.

I could not find any usefull hint in the mathworks help. Do you have any idea? Thanks.


回答1:


There are several ways this can be done, although none of them are clearly the best approach.

One approach is to define everything in a dll and have that loaded by each of the S-Functions. That is outlined in the question How to share a C struct among C S-Functions?.

Another (and my preferred) approach is to create a custom data type, which is a C-struct containing all of the shared data, and have that passed as a signal between the S-Functions in the model. This is outlined in the section Using Opaque Data Types in C S-Functions of the doc Configure Custom Data Types.

The doc shows various (relatively simple) things that need to be done in the S-Function that creates a custom structure. In this S-Functions MdlOutputs method, the custom struct would then just be made the output of the block in the usual way. For example, if the custom struct containing your data is defined as,

typedef struct{
    real_T sig0;
    real_T sig1;
}myStruct;

Then in mdlInitializeSizes you need something like,

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);

And to output this as a signal, in the mdlOutputs method you'd have something like

myStruct *pY0 = (myStruct *)ssGetOutputPortSignal(S, 0);

pY0[0].sig0 = 'value of this param';
pY0[0].sig1 = 'value of this param';

Then in the mdlInitializeSizes of any S-Function that needs to use this signal you need

DTypeId  id;
id = ssRegisterDataType(S, "customDataType");
if(id == INVALID_DTYPE_ID) return;

which then gives you access to the custom struct within any of the other methods by using,

myStruct **uPtrs = (myStruct **) ssGetInputPortSignalPtrs(S,0);

The elements of the struct then get accessed in the usual way,

firstVar = uPtrs[0]->sig0;
secondVar = uPtrs[0]->sig1;

The primary drawback of this approach is that the model cannot be used in code generation (using Simulink Coder).




回答2:


The simplest way for sharing data between S-functions in the generated code would be just to pass it through global variables, in case your S-functions are non-inlined.

Because you get an error with already defined variables, I suppose you're compiling the generated code in a target platform. In this case, it is caused by the duplicate definitions -- global variables have to be defined only in "setup" S-function, and declared with extern keyword in all other S-functions (this is just a plain C in the target).

When S-function is compiled with mex in Simulink environment, it cannot be statically linked to other S-functions. While one can link multiple S-functions with the same external C source file, in the Simulink one will probably get multiple instances of the same data created independently for each S-funciton. Because S-function are compiled and linked independently in the Simulink environment, defining common global variables in each S-function doesn't make sense -- you cannot extern them as they wouldn't be defined for linker (invoked by mex).

The obvious drawback of linking globals on the target is that you can't use Simulink environment to debug functionality which depend on the shared data. But if it's not the main functionality (some supplemental logging for instance), it can be conditionally included with RT flag inside your S-functions to appear only in the generated code allowing to validate the main functionality in the Simulink.



来源:https://stackoverflow.com/questions/53155193/share-data-between-multiple-c-mex-s-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!