Как прочитать Bus объект в C struct внутри C S-Function [Matlab]
Я определил объект Bus в Matlab, и я передаю его в 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-функции?
- Как я могу отключить заполнение, чтобы все данные были смежными?
Заранее спасибо!
2 ответа
У меня такая же проблема. Мне помогли следующие примеры, предоставленные 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
}
Simulink определенным образом организует данные шины в памяти, которые могут не иметь того же макета, что и соответствующая структура C... например, заполнение может быть другим. В результате единственный способ гарантировать, что данные в шине будут помещены в правильное место в структуре C, — это поэлементное копирование.