
/*
 * step_Test_ArrayVoid_SmlkObjO.c C-MEX S-function wrapper.
 *
 *
 * THIS S-FUNCTION IS GENERATED BY jzTc script ".../zbnfjax/Smlk/simulinkSFuncHandle.jzTc" DO NOT MODIFY
 */

/**Must specify the S_FUNCTION_NAME as the name of the S-function.
 */
#define S_FUNCTION_NAME                step_Test_ArrayVoid_SmlkObjO_SfH
#define S_FUNCTION_LEVEL               2

/*
 * Need to include simstruc.h for the definition of the SimStruct and
 * its associated macro definitions.
 */
#include <applstdefJc.h>  //This file is proper defined for the simulink Sfunc environment to define the environment for CRJ 
#include <Fwc/objectBaseC.h>
#undef bool               //it is newly defined in tmwtypes with typedef.
#include "simstruc.h"     //Standard include from mathworks
#include <string.h>  //memset, strcmp
#include <stdlib.h>  //malloc
#include <Fwc/objectBaseC.h>   //The ObjectJc is used as base class for all struct
#include <Jc/reflectionJc.h>   //Access to reflection for bus check necessary
#include <OSAL/os_sharedmem.h> //Support 64-bit-pointer
/*
 * Specific header file(s) required by the S-function.
 */
#include "Test_ArrayVoid_SmlkObjO.h"


  //Info count parameter and ports from C-routines:
  //Object-FB   @simulink defPortTypes: setSizeOutput(...)
  //nrofParamsNoTunable = 0, nrofParamsTunable = 0, nrofParams = 0 
  //ixInputStep = 0, nrofInputs = 1, nrofPorts = 3
  //ixOutputThizInit = 0, ixOutputThizStep = -1 
  //ixOutputInit = 1, ixOutputStep = 1, nrofOutputs = 2


/*
 * Code Generation Environment flag (simulation or standalone target).
 */

static int_T isSimulationTarget;

//A static buffer for preparing error messages. 
static char errorbuffer[1024];

#define EDIT_OK(simstruct, P_IDX) \
 (!((ssGetSimMode(simstruct)==SS_SIMMODE_SIZES_CALL_ONLY) && mxIsEmpty(ssGetSFcnParam(simstruct, P_IDX))))
//#define SAMPLE_TIME                    (ssGetSFcnParam(simstruct, 0))
#define isDWorkNeeded(simstruct)               ((!((ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) && isSimulationTarget==0)) || ssIsRapidAcceleratorActive(simstruct))

/*
 * Utility function prototypes.
 */
//static bool IsRealMatrix(const mxArray *m);
static void CheckDataTypes(SimStruct *simstruct);
static int_T GetRTWEnvironmentMode(SimStruct *simstruct);



//should be comment?


//If set, this is the found step time from Global Workspace Tinit.
static double Tinit = 0;  //This value is set from a global Workspace variable with name 'Tinit'. It should be existing.

static int nrofInputPorts =0, nrofOutputPorts =0, nrofParams =0;

//
//The Tstep and Tstep_offset will be set either from parameter Tstep or Tstep_offset in mdlInitializeSizes(...)
//Or it will be set in mdlSetInputPortSampleTime(...) from the environment model.
//If the parameters are given, the input port gets the sample time of the parameter.
//If the parameters are not given, firstly the ports are initialized with INHERITED_SAMPLE_TIME, 
//then the sample time from the model is associated. The sample time of all inherit ports should be the same. 
//
static double TstepG = INHERITED_SAMPLE_TIME;


//struct to return the info to an indexed port.
typedef struct SmlkPortInfo_t {  DTypeId type; ssComplexity complexity; int arraySize; } SmlkPortInfo;







/**Get the type info for a port from given Entry_DefPortTypeJc.
 * @param ix should be match to the array portTypes, not tested internally.
 */
static void getPortInfo(SmlkPortInfo* info, int ix, Entry_DefPortTypeJc* portType)
{ info->complexity = portType->type >='a' ? COMPLEX_YES : COMPLEX_NO;
  info->arraySize = portType->sizeArray[0];
  if(info->arraySize == 0) { info->arraySize = DYNAMICALLY_SIZED; } 
  switch(portType->type) {
    case 'F': case 'f': info->type = SS_SINGLE; break;
    case 'D': case 'd': info->type = SS_DOUBLE; break;
    case 'I': case 'i': info->type = SS_INT32; break;
    case '4': info->type = SS_UINT32; break;
    case 'S': case 's': info->type = SS_INT16; break;
    case '2': info->type = SS_UINT16; break;
    case 'B': info->type = SS_INT8; break;
    case '1': info->type = SS_UINT8; break;
    case 'b': info->type = SS_UINT8; break;
    default: info->type = DYNAMICALLY_TYPED; info->complexity = COMPLEX_INHERITED; break;
  }                               
}







/* Function: mdlInitializeSizes ===========================================
 * Abstract:
 *    The sizes information is used by Simulink to determine the S-function
 *    block's characteristics (number of inputs, outputs, states, etc.).
 */
static void mdlInitializeSizes(SimStruct *simstruct)
{

  
  /*
   * Get the value returned by rtwenvironmentmode(modelName)
   */
  if (ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) {
    isSimulationTarget = GetRTWEnvironmentMode(simstruct);
    if (isSimulationTarget==-1) {
      ssSetErrorStatus(simstruct,
                       "Unable to determine a valid code generation environment mode.");
      return;
    }

    isSimulationTarget |= ssRTWGenIsModelReferenceSimTarget(simstruct);
  }

  
  
  ssSetNumSFcnParams(simstruct, 0);  //no Parameters, no ctor

#if defined(MATLAB_MEX_FILE)

  if (ssGetNumSFcnParams(simstruct) == ssGetSFcnParamsCount(simstruct)) {
    /*
     * If the number of expected input parameters is not equal
     * to the number of parameters entered in the dialog box return.
     * Simulink will generate an error indicating that there is a
     * parameter mismatch.
     */
    //TODO necessary?
    //mdlCheckParameters(simstruct);
    if (ssGetErrorStatus(simstruct) != NULL) {
      return;
    }
  } else {
    /* Return if number of expected != number of actual parameters */
    return;
  }

#endif

  ssSetNumPWork(simstruct, 0);
  
  
  //Dwork is needed
  if (!ssSetNumDWork(simstruct, 2))  //3 Dwork Pointer, 0 for Bus indices, 1 for thiz handle, 2 for thiz 
    return;

  /*
   * Configure the dwork 0, 2 (thiz)
   */
  ssSetDWorkDataType(simstruct, 0, SS_UINT32);  //for handle thiz
  ssSetDWorkUsageType(simstruct, 0, SS_DWORK_USED_AS_DWORK);
  ssSetDWorkName(simstruct, 0, "thiz_h");
  ssSetDWorkWidth(simstruct, 0, 1);   
  ssSetDWorkComplexSignal(simstruct, 0, COMPLEX_NO);

  //dwork for the allocated thiz
  ssSetDWorkDataType(simstruct, 1, SS_POINTER);  //for thiz itself.
  ssSetDWorkUsageType(simstruct, 1, SS_DWORK_USED_AS_DWORK);
  ssSetDWorkName(simstruct, 1, "thiz");
  ssSetDWorkWidth(simstruct, 1, 1);   
  ssSetDWorkComplexSignal(simstruct, 1, COMPLEX_NO);
  

  
  //This should be set true, because all FBs can be used as multiple instances.
  ssSupportsMultipleExecInstances(simstruct, true);



  double TstepG = INHERITED_SAMPLE_TIME;   
  
  
  
  if(Tinit == 0) { //only 1 time.      
    //Gets the value of the Tinit time from the global workspace variable Tinit.
    int error;
    mxArray* args[2];
    mxArray* out;
    args[0] = mxCreateString("base");
    args[1] = mxCreateString("Tinit");
    error = mexCallMATLAB(1, &out, 2, args, "evalin"); //eval in workspace base
    if(error ==0) { //Tinit found:
      Tinit = *mxGetPr(out);   //gets the double result 
    } else  {
      Tinit = 0.1;  //default value
      ssSetErrorStatus(simstruct,"In step_Test_ArrayVoid_SmlkObjO.: The workspace should contain a variable 'Tinit' with a real value.");
      return;
    }
  }

  //Invoke the @simulink defPortTypes - routine setSizeOutput(...) to determine port types from paramater of the FB:
  struct { DefPortTypesJc head; Entry_DefPortTypeJc __data__[3-1]; } __defPortTypes = {0};
  DefPortTypesJc* _defPortTypes = &__defPortTypes.head; //jzTc.initPorts() - reference variable 
  Entry_DefPortTypeJc* _entryPortTypes = __defPortTypes.head.entries;  
  __defPortTypes.head.size = 3;
  __defPortTypes.head.ixInputStep = 0;
  __defPortTypes.head.ixOutputInit = 1 + 1;
  __defPortTypes.head.ixOutputStep = 1 + 1;

    DefPortTypesJc* portInfo = _defPortTypes;  //jzTc.genDefPorttypes() 
    setSizeOutput(portInfo);
  /*
   * Set the number of input ports.
   */
   
  if (!ssSetNumInputPorts(simstruct, 1))
    return;
  
  /*
   * Configure the input port 0   jzcmd: initPorts()-A
   */

  { SmlkPortInfo info;
    info.type = SS_SINGLE;
    info.complexity = COMPLEX_NO;
    info.arraySize = -1;
    ssSetInputPortDataType(simstruct, 0, info.type); //input port input
    ssSetInputPortWidth(simstruct, 0, info.arraySize);
    ssSetInputPortComplexSignal(simstruct, 0, info.complexity);
  }
  //jzcmd: initPorts()-C
  ssSetInputPortSampleTime(simstruct, 0, TstepG);   //together with ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES)
  ssSetInputPortOffsetTime(simstruct, 0, 0);
  ssSetInputPortDirectFeedThrough(simstruct, 0, 1);
  ssSetInputPortAcceptExprInRTW(simstruct, 0, 1);
  ssSetInputPortOverWritable(simstruct, 0, 1);
  ssSetInputPortOptimOpts(simstruct, 0, SS_REUSABLE_AND_GLOBAL);
  ssSetInputPortRequiredContiguous(simstruct, 0, 1);

  nrofInputPorts = 1;

  /*
   * Set the number of output ports.
   */
   
  if (!ssSetNumOutputPorts(simstruct, 2))
    return;
  nrofOutputPorts = 2;

  ssSetOutputPortDataType(simstruct, 0, SS_UINT32);  //output    //jzTc-initPorts-outputNonBus
  ssSetOutputPortSampleTime(simstruct, 0, Tinit);   //together with ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES)
  ssSetOutputPortOffsetTime(simstruct, 0, 0);
  ssSetOutputPortWidth(simstruct, 0, 1);
  ssSetOutputPortComplexSignal(simstruct, 0, COMPLEX_NO);
  ssSetOutputPortOutputExprInRTW(simstruct, 0, 1);
  ssSetOutputPortOptimOpts(simstruct, 0, SS_REUSABLE_AND_GLOBAL);

  //Configure the output port 1  jzcmd: initPorts()-D

  { SmlkPortInfo info;
    info.type = SS_SINGLE;
    info.complexity = COMPLEX_NO;
    info.arraySize = -1;
    ssSetOutputPortDataType(simstruct, 1, info.type);  //output float output_y  //jzTc-initPorts-outputNonBus
    ssSetOutputPortSampleTime(simstruct, 1, TstepG);   //together with ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES)
    ssSetOutputPortOffsetTime(simstruct, 1, 0);
    ssSetOutputPortWidth(simstruct, 1, info.arraySize);
    ssSetOutputPortComplexSignal(simstruct, 1, info.complexity);
    ssSetOutputPortOutputExprInRTW(simstruct, 1, 1);
    ssSetOutputPortOptimOpts(simstruct, 1, SS_REUSABLE_AND_GLOBAL);
  }


  /*
   * Register reserved identifiers to avoid name conflict
   */
  if (ssRTWGenIsCodeGen(simstruct) || ssGetSimMode(simstruct)==SS_SIMMODE_EXTERNAL) {
    /*
     * Register reserved identifier for InitializeConditionsFcnSpec
     */
    //it seems to be not necessary, the S-functions works proper.
    //ssRegMdlInfo(simstruct, "ctor_Orthi_FB", MDL_INFO_ID_RESERVED, 0, 0, ssGetPath(simstruct));
  }

  /*
   * This S-function can be used in referenced model simulating in normal mode.
   */
  ssSetModelReferenceNormalModeSupport(simstruct, MDL_START_AND_MDL_PROCESS_PARAMS_OK);

  //The sample times should be port based. The handle ports are associated to TstepG because execution order. 
  //
  ssSetNumSampleTimes(simstruct, PORT_BASED_SAMPLE_TIMES); //maybe TstepG is given, if no input ports.
  
  /*
   * Set the compliance with the SimState feature.
   */
  ssSetSimStateCompliance(simstruct, USE_DEFAULT_SIM_STATE);

  /*
   * All options have the form SS_OPTION_<name> and are documented in                
   * matlabroot/simulink/include/simstruc.h. The options should be
   * bitwise or'd together as in
   *   ssSetOptions(simstruct, (SS_OPTION_name1 | SS_OPTION_name2))
   */
  ssSetOptions( simstruct,
                SS_OPTION_USE_TLC_WITH_ACCELERATOR |
                SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
                SS_OPTION_EXCEPTION_FREE_CODE |
                SS_OPTION_WORKS_WITH_CODE_REUSE |
                SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
                SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
                | SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED
              );

#if defined(MATLAB_MEX_FILE)

  if ((ssGetSimMode(simstruct)!=SS_SIMMODE_SIZES_CALL_ONLY) && !ssRTWGenIsCodeGen(simstruct)) {
    /* Verify Data Type consistency with specification */
    CheckDataTypes(simstruct);
  }

#endif

  //TODO necessary ? ssSetSimulinkVersionGeneratedIn(simstruct, "8.7");
}



//
//Set sample time of ports with INHERITED_SAMPLE_TIME.
//It determines the step sample time.
//This routine is invoked only if PORT_BASED_SAMPLE_TIMES are set. It may be need as information for multiple rate blocks too.
//
#define MDL_SET_INPUT_PORT_SAMPLE_TIME 
//This method is used to determine the sample time of that input ports they were set to INHERITED_SAMPLE_TIME
void mdlSetInputPortSampleTime(SimStruct *simstruct, int_T port, real_T sampleTime, real_T offsetTime)
{ int ix;
  TstepG = sampleTime;
  ssSetInputPortSampleTime(simstruct, port, sampleTime);
  ssSetInputPortOffsetTime(simstruct, port, offsetTime);
  //the first invocation sets all other. Ports can be disconnected. Only one inherited sample time.
  for(ix = 0; ix < 1; ++ix) {
    if(ssGetInputPortSampleTime(simstruct, ix) == INHERITED_SAMPLE_TIME) {
      ssSetInputPortSampleTime(simstruct, ix, sampleTime);
      ssSetInputPortOffsetTime(simstruct, ix, offsetTime);
    }
  }
  for(ix = 0; ix < 2; ++ix) {
    if(ssGetOutputPortSampleTime(simstruct, ix) == INHERITED_SAMPLE_TIME) {
      ssSetOutputPortSampleTime(simstruct, ix, sampleTime);
      ssSetOutputPortOffsetTime(simstruct, ix, offsetTime);
    }
  }
}


#define MDL_SET_OUTPUT_PORT_SAMPLE_TIME
//This method is used to determine the sample time of that output ports they were set to INHERITED_SAMPLE_TIME
void mdlSetOutputPortSampleTime(SimStruct *simstruct, int_T port, real_T sampleTime, real_T offsetTime)
{
  ssSetOutputPortSampleTime(simstruct, port, sampleTime);
  ssSetOutputPortOffsetTime(simstruct, port, offsetTime);
}












#define MDL_INITIALIZE_SAMPLE_TIMES
/* Function: mdlInitializeSampleTimes =====================================
 * Abstract:
 *    This function is used to specify the sample time(s) for your
 *    S-function. You must register the same number of sample times as
 *    specified in ssSetNumSampleTimes.
 */
static void mdlInitializeSampleTimes(SimStruct *simstruct)
{
  int ix;
  //Check all input ports whether there sample time is known.
  //Note: the sample time is not known in test, whats happen?
  //Only test:
  for(ix = 0; ix < nrofInputPorts; ++ix) {
    double time = ssGetInputPortSampleTime(simstruct, ix);
    if(time == Tinit){ }
    else if(TstepG == -1) { TstepG = time; }
    else if(time != TstepG) {
      //a second time, warning
    }
    else {} //time is known already.
  }
   
#if defined(ssSetModelReferenceSampleTimeDefaultInheritance)

  ssSetModelReferenceSampleTimeDefaultInheritance(simstruct);

#endif

}






//
//Sub routine to set the known port types and sizes and to invoke the users "@simulink defPortTypes" routine.
//Before call the yet known port types are stored in the Entry_DefPortTypeJc[] array
//to give information about that to determine the yet not typed ports.
//The users "@simulink defPortTypes" routine is not called if the cause is 'kRun_EPropagatePortTypesJc'.
//This is to fill the DefPortTypesJc struct with the types and sizes of all ports before the ctor-, init- or step-routine
// 
void invokeDefPortTypes(SimStruct *simstruct, DefPortTypesJc* _defPortTypes, EDefPortTypesJc cause)  
{ //stack local array, the user routine must not store the reference!    
  //Note: because the ctor is not invoked in this time, and DWork cannot be used in this time, no instance data are possible.
  int ixPort;
  char cType;
  int sizeType;
  Entry_DefPortTypeJc* entryPortTypes = _defPortTypes->entries; 
  //fill struct with known port properties, but not in initalizeConditions, there the ports are not defined yet.
  for(ixPort = 0; ixPort < 1; ++ixPort) {
    Entry_DefPortTypeJc* entryPortType = &entryPortTypes[ixPort];  //dst to set
    DTypeId type = ssGetInputPortDataType(simstruct, ixPort);
    switch(type) {
      case SS_DOUBLE: cType = 'D'; sizeType = 8; break; 
      case SS_SINGLE: cType = 'F'; sizeType = 4; break;
      case SS_INT32:  cType = 'I'; sizeType = 4; break;
      case SS_INT16:  cType = 'S'; sizeType = 2; break;
      case SS_INT8:   cType = 'B'; sizeType = 1; break;
      case SS_UINT32: cType = '4'; sizeType = 4; break;
      case SS_UINT16: cType = '2'; sizeType = 2; break;
      case SS_UINT8:  cType = '1'; sizeType = 1; break;
      default:        cType = 0;   sizeType = 0; break;
    }
    if(ssGetInputPortComplexSignal(simstruct, ixPort) == COMPLEX_YES) { cType += ('a'-'A'); sizeType *=2; } //to lower case; 
    entryPortType->type = cType;  
    entryPortType->sizeType = sizeType;  

    int size = ssGetInputPortWidth(simstruct, ixPort); 
    if(size == DYNAMICALLY_SIZED) {
      entryPortType->dimensions = 0;
      entryPortType->sizeArray[0] = 0;
    } else {
      entryPortType->dimensions = 1;
      entryPortType->sizeArray[0] = size;
    }
  }
  for(ixPort = 0; ixPort < 2; ++ixPort) {
    Entry_DefPortTypeJc* entryPortType = &entryPortTypes[1 + ixPort];  //dst to set
    DTypeId type = ssGetOutputPortDataType(simstruct, ixPort);
    switch(type) {
      case SS_DOUBLE: cType = 'D'; sizeType = 8; break; 
      case SS_SINGLE: cType = 'F'; sizeType = 4; break;
      case SS_INT32:  cType = 'I'; sizeType = 4; break;
      case SS_INT16:  cType = 'S'; sizeType = 2; break;
      case SS_INT8:   cType = 'B'; sizeType = 1; break;
      case SS_UINT32: cType = '4'; sizeType = 4; break;
      case SS_UINT16: cType = '2'; sizeType = 2; break;
      case SS_UINT8:  cType = '1'; sizeType = 1; break;
      default:        cType = 0;   sizeType = 0; break;
    }
    if(ssGetOutputPortComplexSignal(simstruct, ixPort) == COMPLEX_YES) { cType += ('a'-'A'); ; sizeType *=2; } //to lower case; 
    entryPortType->type = cType; 
    int size = ssGetOutputPortWidth(simstruct, ixPort); 
    entryPortType->sizeType = sizeType;  

    if(size == DYNAMICALLY_SIZED) {
      entryPortType->dimensions = 0;
      entryPortType->sizeArray[0] = 0;
    } else {
      entryPortType->dimensions = 1;
      entryPortType->sizeArray[0] = size;
    }
  }
  if(cause != kRun_EPropagatePortTypesJc) {
    
    DefPortTypesJc* portInfo = _defPortTypes;  //jzTc.genDefPorttypes() 
    setSizeOutput(portInfo);
  }
}


#if defined(MATLAB_MEX_FILE)

#define MDL_SET_INPUT_PORT_DATA_TYPE
#define MDL_SET_OUTPUT_PORT_DATA_TYPE
void mdlSetInputPortDataType(SimStruct *simstruct, int_T port, DTypeId id)
{ ssSetInputPortDataType(simstruct, port, id);
}

void mdlSetOutputPortDataType(SimStruct *simstruct, int_T port, DTypeId id)
{ ssSetOutputPortDataType(simstruct, port, id);
  //in manually written routines the user may store the definition of this special port, 
  //use it for own algorithm and determine related ports.
  //In the jzTc generation this is done by invocation of the "@simulink defPortTypes" routine
  //in the Sfunction routine "mdlSetDefaultPortDataTypes". There the current situation of port types is gathered and delivered. 
}



#define MDL_SET_DEFAULT_PORT_DATA_TYPES
//set the ports which were note determined by wiring in the model.
//It is possible that the _entryPortTypes_SfuncGLOBAL structure are filled with the associated port.
//Then use it. Else default is int32
void mdlSetDefaultPortDataTypes(SimStruct *simstruct)
{ int ix;
  
  struct { DefPortTypesJc head; Entry_DefPortTypeJc __data__[3-1]; } defPortTypes = {0};
  Entry_DefPortTypeJc* entryPortTypes = defPortTypes.head.entries;
  defPortTypes.head.size = 3;
  defPortTypes.head.ixInputStep = 0;
  defPortTypes.head.ixOutputInit = 1 + 1;
  defPortTypes.head.ixOutputStep = 1 + 1;
  invokeDefPortTypes(simstruct, &defPortTypes.head, kSetType_EPropagatePortTypesJc);
  
  for(ix = 0; ix < 1; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetInputPortDataType(simstruct, ix) == DYNAMICALLY_TYPED) {
      int type;
      
      switch(entryPortTypes[ix].type) {
        case 'F': type = SS_SINGLE; break;
        case 'D': type = SS_DOUBLE; break;
        case 'I': type = SS_INT32; break;
        case 'S': type = SS_INT16; break;
        case 'B': type = SS_INT8; break;
        case '4': type = SS_UINT32; break;
        case '2': type = SS_UINT16; break;
        case '1': type = SS_UINT8; break;
        default: type = SS_INT32; entryPortTypes[ix].type = 'I'; break;
      }
      
      ssSetInputPortDataType(simstruct, ix, type);
    }
  }	
  for(ix = 0; ix < 2; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetOutputPortDataType(simstruct, ix) == DYNAMICALLY_TYPED) {
      int type;
      
      switch(entryPortTypes[ix + 1].type) {
        case 'F': type = SS_SINGLE; break;
        case 'D': type = SS_DOUBLE; break;
        case 'I': type = SS_INT32; break;
        case 'S': type = SS_INT16; break;
        case 'B': type = SS_INT8; break;
        case '4': type = SS_UINT32; break;
        case '2': type = SS_UINT16; break;
        case '1': type = SS_UINT8; break;
        default: type = SS_INT32; entryPortTypes[ix].type = 'F';break;
      }
      
      ssSetOutputPortDataType(simstruct, ix, type);
    }
  }	
}


#define MDL_SET_INPUT_PORT_DIMENSION_INFO
#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
static void mdlSetInputPortDimensionInfo(SimStruct *simstruct, int_T port, const DimsInfo_T *dimsInfo)
{
	if (!ssSetInputPortDimensionInfo(simstruct, port, dimsInfo)) return;
}

static void mdlSetOutputPortDimensionInfo(SimStruct *simstruct, int_T port, const DimsInfo_T *dimsInfo)
{
	if (!ssSetOutputPortDimensionInfo(simstruct, port, dimsInfo)) return;
}

void mdlSetDefaultPortDimensionInfo(SimStruct *simstruct)
{ int ix;
  
  struct { DefPortTypesJc head; Entry_DefPortTypeJc __data__[3-1]; } defPortTypes = {0};
  Entry_DefPortTypeJc* entryPortTypes = defPortTypes.head.entries;
  defPortTypes.head.size = 3;
  defPortTypes.head.ixInputStep = 0;
  defPortTypes.head.ixOutputInit = 1 + 1;
  defPortTypes.head.ixOutputStep = 1 + 1;
  invokeDefPortTypes(simstruct, &defPortTypes.head, kSetType_EPropagatePortTypesJc);
  
  for(ix = 0; ix < 1; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetInputPortWidth(simstruct, ix) == DYNAMICALLY_SIZED) {
      
      int dim = entryPortTypes[ix].sizeArray[0];
      if(dim <=0) { dim = 1; }
      
      ssSetInputPortWidth(simstruct, ix, dim);
    }
  }	
  for(ix = 0; ix < 2; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetOutputPortWidth(simstruct, ix) == DYNAMICALLY_SIZED) {
      
      int dim = entryPortTypes[1 + ix].sizeArray[0];
      if(dim <=0) { dim = 1; }
      
      ssSetOutputPortWidth(simstruct, ix, dim);
    }
  }	
}



#define MDL_SET_INPUT_PORT_COMPLEX_SIGNAL
#define MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL
void mdlSetInputPortComplexSignal(SimStruct *simstruct, int_T port,  CSignal_T csig)
{
  ssSetInputPortComplexSignal(simstruct, port, csig);
}

void mdlSetOutputPortComplexSignal(SimStruct *simstruct, int_T port,  CSignal_T csig)
{
  ssSetOutputPortComplexSignal(simstruct, port, csig);
}

#define MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS
void mdlSetDefaultPortComplexSignals(SimStruct *simstruct)
{ int ix;
  
  struct { DefPortTypesJc head; Entry_DefPortTypeJc __data__[3-1]; } defPortTypes = {0};  
  Entry_DefPortTypeJc* entryPortTypes = defPortTypes.head.entries;
  defPortTypes.head.size = 3;
  defPortTypes.head.ixInputStep = 0;
  defPortTypes.head.ixOutputInit = 1 + 1;
  defPortTypes.head.ixOutputStep = 1 + 1;
  invokeDefPortTypes(simstruct, &defPortTypes.head, kSetType_EPropagatePortTypesJc);
  
  for(ix = 0; ix < 1; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetInputPortComplexSignal(simstruct, ix) != COMPLEX_YES) {
      
      int complexity = entryPortTypes[ix].type >='a' ? COMPLEX_YES : COMPLEX_NO;
      
      ssSetInputPortComplexSignal(simstruct, ix, complexity);
    }
  }	
  for(ix = 0; ix < 2; ++ix) {
    if(entryPortTypes[ix].newDefined || ssGetInputPortComplexSignal(simstruct, ix) != COMPLEX_YES) {
      
      int complexity = entryPortTypes[1 + ix].type >='a' ? COMPLEX_YES : COMPLEX_NO;
      
      ssSetOutputPortComplexSignal(simstruct, ix, complexity);
    }
  }	
}

#endif //MATLAB_MEX_FILE




#define MDL_SET_WORK_WIDTHS
#if defined(MDL_SET_WORK_WIDTHS) && defined(MATLAB_MEX_FILE)

/* Function: mdlSetWorkWidths =============================================
 * Abstract:
 *      The optional method, mdlSetWorkWidths is called after input port
 *      width, output port width, and sample times of the S-function have
 *      been determined to set any state and work vector sizes which are
 *      a function of the input, output, and/or sample times.
 *
 *      Run-time parameters are registered in this method using methods
 *      ssSetNumRunTimeParams, ssSetRunTimeParamInfo, and related methods.
 */
static void mdlSetWorkWidths(SimStruct *simstruct)
{
  

  ssSupportsMultipleExecInstances(simstruct, true);
}

#endif


#include <Fwc/fw_handle_ptr64.h>



#define MDL_START
#if defined(MDL_START)

/* Function: mdlStart =====================================================
 * Abstract:
 *    This function is called once at start of model execution. If you
 *    have states that should be initialized once, this is the place
 *    to do it.
 */
static void mdlStart(SimStruct *simstruct)
{
  if (isDWorkNeeded(simstruct)) {
    //
    //===============Get the address of the structure to convert handle values to pointer===============================
    //Note: If more as one instance of this FB will be created, the mdlStart is invoked for any instance.
    //      But there is only one static shMemHandle2Ptr. The first mdlStart creates it. Don't call twice!
    //       
    //
    char const* error = init_Handle2Ptr(1000);
    if(error !=null) {
      ssSetErrorStatus(simstruct, error); // Sfunc=step_Test_ArrayVoid_SmlkObjO");
      return;
    }
    
    
    //
    
  { //Allocates the memory for the bus data for the C-function.
    //The bus data are allocated for this instance especially. 
    //jzcmd: setBusInfo_mdlStart()-A
    char const* error;
    uint32 handle;
    int size1 = (int)sizeof(Test_ArrayVoid_SmlkObjO);
    ObjectJc* ptr = (ObjectJc*)calloc(size1+1024, 1);
    if (ptr==NULL) {
      ssSetErrorStatus(simstruct,"Unexpected error during the memory allocation for Test_ArrayVoid_SmlkObjO");
      return;
    }
    init_ObjectJc(ptr, size1, ident_newAllocated_ObjectJc);
    void** addr_ptr = (void**) ssGetDWork(simstruct, 1);  //there is only one DWork, for thiz or thiz_y
    if(addr_ptr !=null) {
      *addr_ptr = ptr;
    } else {
      ssSetErrorStatus(simstruct,"DWork(2) not existent:  ctor_Test_ArrayVoid_SmlkObjO");
    }
    error = registerPtr_Handle2Ptr(ptr, "ctor_Test_ArrayVoid_SmlkObjO", &handle);
    if(error !=null) {
      ssSetErrorStatus(simstruct,error);
      return;
    }
    uint32* addr_handle = (uint32*) ssGetDWork(simstruct, 0);  //there is only one DWork, for thiz or thiz_y
    if(addr_handle !=null) {
      *addr_handle = handle;
    } else {
      ssSetErrorStatus(simstruct,"DWork(1) not existent:  ctor_Test_ArrayVoid_SmlkObjO");
    }
    //
  }


  }
}

#endif











#define MDL_INITIALIZE_CONDITIONS
#if defined(MDL_INITIALIZE_CONDITIONS)

/* Function: mdlInitializeConditions ======================================
 * Abstract:
 *    In this function, you should initialize the states for your S-function block.
 *    You can also perform any other initialization activities that your
 *    S-function may require. Note, this routine will be called at the
 *    start of simulation and if it is present in an enabled subsystem
 *    configured to reset states, it will be call when the enabled subsystem
 *    restarts execution to reset the states.
 */
static void mdlInitializeConditions(SimStruct *simstruct)
{
  if (isDWorkNeeded(simstruct)) {
    
    //jzTc-ctor-arg thiz:
    Test_ArrayVoid_SmlkObjO** addr_thiz = (Test_ArrayVoid_SmlkObjO**)ssGetDWork(simstruct,1);  //jzTc: genCtor thiz
    ObjectJc* othiz = (ObjectJc*)*addr_thiz;  //cast admissible because the instance have to be based on ObjectJc
    Test_ArrayVoid_SmlkObjO* thiz = *addr_thiz;              //checkStrict_ObjectJc is invoked.
    //jzTc-ctor-arg 'portInfo': Info about all ports. stack local struct to hold info about ports
    struct { DefPortTypesJc head; Entry_DefPortTypeJc __data__[3-1]; } _defPortTypes = {0};  
    DefPortTypesJc* portInfo = &_defPortTypes.head;  //argument variable for step routine       
    _defPortTypes.head.size = 3;
    _defPortTypes.head.ixInputStep = 0;
    _defPortTypes.head.ixOutputInit = 1 + 1;
    _defPortTypes.head.ixOutputStep = 1 + 1;
    invokeDefPortTypes(simstruct, &_defPortTypes.head, kRun_EPropagatePortTypesJc);  //fill the local array with port info.

    { if( -1 == checkStrict_ObjectJc(othiz, (int32)sizeof(Test_ArrayVoid_SmlkObjO), ident_newAllocated_ObjectJc, null, null)) {
        ssSetErrorStatus(simstruct,"malloc faulty for ctor_Test_ArrayVoid_SmlkObjO");
      }
      //jzTc: Call of the constructor:
      ctor_Test_ArrayVoid_SmlkObjO( thiz, portInfo);
    }

  }
}

#endif













/* Function: mdlUpdate ===================================================*/
//not used not necessary.
#define MDL_UPDATE 
#if defined(MDL_UPDATE) && defined(MATLAB_MEX_FILE) 
static void mdlUpdate(SimStruct *simstruct, int_T tid)
{ if (isDWorkNeeded(simstruct)) {
    tid +=1;  //nop, for break point.
  }
}
#endif





/* Function: mdlOutputs ===================================================
 * Abstract:
 *    In this function, you compute the outputs of your S-function
 *    block. Generally outputs are placed in the output vector(s),
 *    ssGetOutputPortSignal.
 */
#define MDL_OUTPUT 
static void mdlOutputs(SimStruct *simstruct, int_T tid)
{ if (isDWorkNeeded(simstruct)) {
    
    //Object-FB:  
    //params: ix-init = 0, ix-step = 0, nrof = 0  
    //input ports: ix-init = X, ix-step = 0, nrof = 1  
    //output ports: thizInit = 0, thizStep = -1, ix-init = X, ix-step = 1, nrof = 2  

    char const* error = null;

    //Object-FB, thiz from DWork[1], handle from DWork[0]:    
    Test_ArrayVoid_SmlkObjO* thiz = *(Test_ArrayVoid_SmlkObjO **)ssGetDWork(simstruct, 1 );
    uint32 hthiz = *(uint32*)ssGetDWork(simstruct, 0 );  //get handle stored in DWork in mdlStart(...)

    uint32* addr_thizInit = (uint32*)ssGetOutputPortSignal(simstruct, 0);  //address of thiz output for init time
    *addr_thizInit = hthiz;        //output the handle always, for Tinit time. Note: init().routines are exexuted at beginn of step time. 

    //jzcmd: genStepMethod()-B
    float * output_y = (float *)ssGetOutputPortSignal(simstruct, 1);  //gets the address of the output data in Simulink data area.

    //Sampletimes used: Tinit = true  Tstep = true

    //Port based sample time nrofInputs = 1, ixInputStep = 0, ixOutputStep = 1  
    int sti;
    time_T time_SmlkStep_ = ssGetT(simstruct);

    sti = ssGetInputPortSampleTimeIndex(simstruct,0);  //check the first input of the step method (zbnfop)
    //sti = ssGetOutputPortSampleTimeIndex(simstruct,1);  //The 2. Output is always in Tstep on an Object-FB
    if (ssIsSampleHit(simstruct, sti, tid)) {
      time_T time_SmlkStep_ = ssGetT(simstruct);

      if( isInitialized_ObjectJc((ObjectJc*)thiz) ) {

          //JZtc: The input port supplies the address of the array:      
          float const* input = (float const*)ssGetInputPortSignal(simstruct, 0);
    
        //invoke the step-routine: jzTc: genStepMethod()-E
        step_Test_ArrayVoid_SmlkObjO(thiz, input, output_y);

   } } //

  }
}










    
/* Function: mdlTerminate =================================================
 * Abstract:
 *    In this function, you should perform any actions that are necessary
 *    at the termination of a simulation.
 */
static void mdlTerminate(SimStruct *simstruct)
{
  if (isDWorkNeeded(simstruct)) {
    
  //Free the memory for the Test_ArrayVoid_SmlkObjO data //jzcmd: freeMem_mdlTerminate()-A
  Test_ArrayVoid_SmlkObjO** addr_thiz = (Test_ArrayVoid_SmlkObjO**)ssGetDWork(simstruct, 1); 
  Test_ArrayVoid_SmlkObjO* thiz = *addr_thiz;
  if(thiz != NULL) {
    free(thiz);
  }
  //close the sharedmem handle:
  //Note: If more as one instance of this FB was created, the mdlTerminate is invoked for any instance.
  //      But there is only one static shMemHandle2Ptr. The first mdlTerminate removes it.
  //       
  close_Hande2Ptr();

  }
}







#define MDL_RTW
#if defined(MATLAB_MEX_FILE) && defined(MDL_RTW)

/* Function: mdlRTW =======================================================
 * Abstract:
 *    This function is called when Simulink Coder is generating
 *    the model.rtw file.
 */
static void mdlRTW(SimStruct *simstruct)
{ 
}

#endif


/* Function: CheckDataTypeChecksum ======================================
 * Abstract:
 *    CheckDataTypeChecksum invokes a MATLAB helper for checking the consistency
 *    between the data type definition used when this S-Function was generated
 *    and the data type used when calling the S-Function.
 */
static int_T CheckDataTypeChecksum(SimStruct *simstruct, const char* dtypeName, uint32_T*
  chkRef)
{
  mxArray *plhs[1] = { NULL };

  mxArray *prhs[3];
  mxArray *err = NULL;
  const char *bpath = ssGetPath(simstruct);
  int_T status = -1;
  prhs[0] = mxCreateString(bpath);
  prhs[1] = mxCreateString(dtypeName);
  prhs[2] = mxCreateDoubleMatrix(1, 4, mxREAL);
  mxGetPr(prhs[2])[0] = chkRef[0];
  mxGetPr(prhs[2])[1] = chkRef[1];
  mxGetPr(prhs[2])[2] = chkRef[2];
  mxGetPr(prhs[2])[3] = chkRef[3];
  err = mexCallMATLABWithTrap(1, plhs, 3, prhs,
    "legacycode.LCT.getOrCompareDataTypeChecksum");
  mxDestroyArray(prhs[0]);
  mxDestroyArray(prhs[1]);
  mxDestroyArray(prhs[2]);
  if (err==NULL && plhs[0]!=NULL) {
    status = mxIsEmpty(plhs[0]) ? -1 : (int_T) (mxGetScalar(plhs[0]) != 0);
    mxDestroyArray(plhs[0]);
  }

  return status;
}













/* Function: CheckDataTypes =============================================
 * Abstract:
 *    CheckDataTypes verifies data type consistency between the data type
 *    definition used when this S-Function was generated and the data type
 *    used when calling the S-Function.
 */
static void CheckDataTypes(SimStruct *simstruct)
{
 
  //TODO check with known bus element names and their types.
  //from where is the check sum?
  /* Verify Bus/StructType 'Param_Orthi_FB', specification * /
  {
    uint32_T chk[] = { 4189326214, 1854717099, 3653914067, 1841847726 };

    int_T status;
    status = CheckDataTypeChecksum(simstruct, "Param_Orthi_FB", &chk[0]);
    if (status==-1) {
      ssSetErrorStatus(simstruct,
                       "Unexpected error when checking the validity of the Simulink Bus/StructType 'Param_Orthi_FB'");
    } else if (status==0) {
      ssSetErrorStatus(simstruct,
                       "The Simulink Bus/StructType 'Param_Orthi_FB' definition has changed since the S-Function was generated");
    }
  }
  TODO */
}











/* Function: GetRTWEnvironmentMode ======================================
 * Abstract:
 *    Must be called when ssRTWGenIsCodeGen(simstruct)==true. This function
 *    returns the code generation mode:
 *      -1 if an error occurred
 *       0 for standalone code generation target
 *       1 for simulation target (Accelerator, RTW-SFcn,...)
 */
static int_T GetRTWEnvironmentMode(SimStruct *simstruct)
{
  int_T status;
  mxArray *plhs[1];
  mxArray *prhs[1];
  int_T err;

  /*
   * Get the name of the Simulink block diagram
   */
  prhs[0] = mxCreateString(ssGetModelName(ssGetRootSS(simstruct)));
  plhs[0] = NULL;

  /*
   * Call "isSimulationTarget = rtwenvironmentmode(modelName)" in MATLAB
   */
  mexSetTrapFlag(1);
  err = mexCallMATLAB(1, plhs, 1, prhs, "rtwenvironmentmode");
  mexSetTrapFlag(0);
  mxDestroyArray(prhs[0]);

  /*
   * Set the error status if an error occurred
   */
  if (err) {
    if (plhs[0]) {
      mxDestroyArray(plhs[0]);
      plhs[0] = NULL;
    }

    ssSetErrorStatus(simstruct, "Unknown error during call to 'rtwenvironmentmode'.");
    return -1;
  }

  /*
   * Get the value returned by rtwenvironmentmode(modelName)
   */
  if (plhs[0]) {
    status = (int_T) (mxGetScalar(plhs[0]) != 0);
    mxDestroyArray(plhs[0]);
    plhs[0] = NULL;
  }

  return (status);
}

/*
 * Required S-function trailer
 */
#ifdef MATLAB_MEX_FILE
# include "simulink.c"
#else
# include "cg_sfun.h"
#endif

