如何在C S-Function中将Bus对象读入C struct [Matlab]

oewdyzsn  于 2023-08-03  发布在  Matlab
关注(0)|答案(2)|浏览(118)

我在Matlab中定义了一个Bus对象,并将其传递给一个C S函数,该函数将进行一些处理。我在mdlInitializeSizes中初始化输入如下:

#if defined(MATLAB_MEX_FILE)
    if (ssGetSimMode(S) != SS_SIMMODE_SIZES_CALL_ONLY)
    {
        DTypeId dataTypeIdReg;

        ssRegisterTypeFromNamedObject(S, BUS_OBJ_NAME, &dataTypeIdReg);
        if(dataTypeIdReg == INVALID_DTYPE_ID) return;
        ssSetInputPortDataType(S, 0, dataTypeIdReg);
    }
#endif
ssSetInputPortWidth(S, 0, 1);
ssSetBusInputAsStruct(S, 0, 1); 
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortRequiredContiguous(S, 0, 1);

字符串
我还自动生成了一个C结构体,其中包含与Bus对象中的信号相同的变量。
总线中的一些信号也是总线,因此C结构体是递归生成的。举例来说:

struct myStruct
{
   uint8_t var1[8];
   uint32_t var2;
   myOtherStruct1 var3;
   myOtherStruct2 var4;
   ...
}


现在我想把Bus对象读入结构体。为此,我做到了:

const myStruct *busData = (const myStruct *) ssGetInputPortSignal(S, 0);


问题是busData没有var4和以下变量的正确数据。如果我打印从ssGetInputPortSignal接收的原始数据,我可以找到我期望的数据,但它不在数组中的正确位置;相反,它有一些**填充。
因此我想问:

  • 这是将Bus对象读入C S函数中的结构体的正确方法吗?
  • 如何禁用填充,使所有数据都是连续的?

提前感谢!

7gs2gvoe

7gs2gvoe1#

我也有同样的问题。帮助我的是MathWorks提供的以下示例:

open('sldemo_sfun_counterbus.c')
open('counterbus.h')

字符串
下面是一些代码片段,展示了如何根据上面的示例获取simulink总线对象的信息:

// Defined localy, could also be defined in a header
typedef struct                  
{                               
    uint32_t ui32_header_val;   
    double f64_header_val;      
} YOURSTRUCT;            

static void mdlInitializeSizes(SimStruct *S)
{
    // ... your code

    // Specify I/O
    if (!ssSetNumInputPorts(S,1)) return;

    //Bus inport 
    DTypeId dataTypeIdReg;
    ssRegisterTypeFromNamedObject(S, "YOURBUS", &dataTypeIdReg);
    ssSetInputPortDataType(S, 0, dataTypeIdReg);
    ssSetBusInputAsStruct(S, 0, true);

    ssSetInputPortOverWritable(S, 0, 1);
    ssSetInputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
    // This is important !!! Specifies that the signal elements entering the specified port must occupy contiguous areas of memory
    ssSetInputPortRequiredContiguous(S, 0, 1);

    // Configure the dwork (__dtBusInfo)
    ssSetDWorkDataType(S, 0, SS_INT32);
    ssSetDWorkUsageType(S, 0, SS_DWORK_USED_AS_DWORK);
    ssSetDWorkName(S, 0, "dtBusInfo");

    // This contains the offset and sizes of your struct
    ssSetDWorkWidth(S, 0, 4);
    // The DWorker needs a depth of 4, since it stores the size of each element and its offset

    ssSetDWorkComplexSignal(S, 0, COMPLEX_NO);

    // ... your code
}

static void mdlStart(SimStruct *S)
{
    // ... your code

    // Access bus/struct information
    int32_T* __dtBusInfo = (int32_T*)ssGetDWork(S, 0);

    // Get common data type Id 
    DTypeId __YOURBUSId = ssGetDataTypeId(S, "YOURBUS");
    DTypeId __int32Id = ssGetDataTypeId(S, "int32");
    DTypeId __doubleId = ssGetDataTypeId(S, "double");

    // Get information for accessing YOURBUS.ui32_header_val
    __dtBusInfo[0] = ssGetBusElementOffset(S, __YOURBUSId, 0);
    __dtBusInfo[1] = ssGetDataTypeSize(S, __int32Id);

    // Get information for accessing YOURBUS.f64_header_val
    __dtBusInfo[2] = ssGetBusElementOffset(S, __YOURBUSId, 1);
    __dtBusInfo[3] = ssGetDataTypeSize(S, __doubleId);

    // ... your code                  

static void mdlOutputs(SimStruct *S, int_T tid)
{   
    // ... your code
    char *inputPort = (char*)(ssGetInputPortSignal(S, 0)); // Cast it to an 8Bit long Pointer here char

    YOURSTRUCT yourCStruct;

    memcpy(&yourCStruct.ui32_header_val, inputPort + __dtBusInfo[0], __dtBusInfo[1]);
    memcpy(&yourCStruct.f64_header_val,  inputPort + __dtBusInfo[2], __dtBusInfo[3]);
    // ... your code
}

k97glaaz

k97glaaz2#

Simulink在内存中以某种方式组织总线数据,其布局可能与相应的C结构不同。例如填充可以不同。因此,确保总线中的数据被放置在C结构中的正确位置的唯一方法是逐个元素的复制。
https://www.mathworks.com/matlabcentral/answers/595120-structure-output-from-s-function-getting-memcopy-ed-one-element-at-a-time-when-connecting-to-bus-por

相关问题