简体   繁体   中英

Represent C struct of pointers using Simulink Bus

How can I associate a C struct of pointers with Simulink.Bus ?

Say I've C struct:

typedef struct 
{
    int32_T *a;
    uint8_T *b;
} Bus_X ;

then for Simulink.Bus.objectToCell

 { ...
           'Bus_X', ...
           'Bus.h', ...
           sprintf(''), ...
           'Imported', {...
           {'a', 1, '???', -1, 'real', 'Sample', 'Fixed'}; ...
           {'b', 1, '???', -1, 'real', 'Sample', 'Fixed'}; ...
           } ...
 } ...

What shall be the '???'

I want to use it like following in external C code as

Bus_X x_data = { &a_sig, &b_sig  };
Bus_X* x_ptr = &x_data;

where x_ptr will be ImportedExternPointer on Simulink Signal

Then, if this is possible, Simulink should do magic in generated code like :

*(x_ptr->a) = 42.0 ;

It is possible to deal with pointer in Simulink Buses which can be used in C in generated code, or in S-functions, not in pure Simulink.

The last one, I think simulink has a paradigm: Data flow from input to output. Pointers offers the possibility to set data backward, from an output bus into the module. That is not desired, therefore pointers in buses are not firstly supported. But for solutions in the C-environment pointers may be a point of interest.

In the header file you should define a union:

typedef struct MyBus_t { union { int32 myRefBus_int[2]; MyRefBus* myRefBus; } /*unnamed union*/ ; //... some more elements; } MyBus;

The Simulink Bus definition should contain only the myRefBus_int element as int32 array of 2 dimensions. The next topic is a S-function which converts any desired Bus to the int32[]. S-functions have pointers as input if the input is a bus at model level. Arrays are also presented as pointners. Therefore the S-function "Bus2ptr" has the following definition in the mex.c file:

static void mdlInitializeSizes(SimStruct *simstruct) {

ssSetInputPortWidth(simstruct, 0, 1);
ssSetInputPortDataType(simstruct, 0, DYNAMICALLY_TYPED);
ssSetOutputPortDataType(simstruct, 0, SS_INT32);
ssSetOutputPortWidth(simstruct, 0, 2);


}
 static void mdlOutputs(SimStruct *simstruct, int_T tid)
 {  
  void const*const* ptrs = ssGetInputPortSignalPtrs(simstruct, 0);  //InputPtrsType, InputRealPtrsType etc.
  void** x = (void**) ptrs[0];  
  int32* y = (int32*)ssGetOutputPortSignal(simstruct, 0);
  int64 ptr = (int64)(*x);
  y[0] = (int32)ptr;
  y[1] = (int32)(ptr >>32);  //assume little endian. It is proper for all PC processors.
 }

There are used two int32 because it should run on a 64 bit PC. The tlc-file contains the line:

 %function Outputs(block, system) Output
  %assign u1_ptr = LibBlockInputSignal(0, "", "", 0)
  %assign y1_ptr = LibBlockOutputSignalAddr(0, "", "", 0)
  *(int32*)(u1_ptr) = (int32)(u1_ptr);

For a 32-bit target system you need only 1 element. With this S-function you can convert any bus to int32-array and store the int32 values which is the address in the bus structure. From C level you can use the other union element in the bus header struct.

If I have enougth time this weekend I will describe some more at my internet page www.vishia.org . Yet there is nothing about simulink stored there. But I will open a presentation corner for simulink in the next time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM