2

How to determine the type of a pointer indexed member. I intend to use:

TYPE DUT_DemoStruct :
STRUCT
        Member_1: BOOL;
        Member_2: INT;
END_STRUCT
END_TYPE


PROGRAM Prg_Main
VAR
        DemoStructPointer:
        Obj_DemoStruct1: DUT_DemoStruct ;
        Obj_DemoStruct2: DUT_DemoStruct ;
        Obj_DemoStruct3: DUT_DemoStruct ;
        Demo_INT: INT;
        Index: INT;
        _pointer: POINTER TO DUT_DemoStruct;
END_VAR


FOR Index:=0 TO 5 DO
        IF _pointer[Index] THEN  //whether the _pointer[Index] (pointer index member) is of type DUT_DemoStruct
            _pointer[Index].Member_1:=TRUE;
        END_IF;
END_FOR;

In addition, Do you have any application cases for CheckPointer?

EDIT:2022-06-05

This is to better implement the contracted part of the HMSD(Hierarchical Master-Slave Distribution) framework. For example, batch initialization of states. For example: if you want to implement batch initialization of objects of class Step, you only need to pass the pointer of the first Step to the initialization function, and the function will automatically search down according to the first pointer until it finds an object that is not of the Step class and stops searching. This process needs to be automated. To achieve such a function, you need the index of the pointer, and determine the type of the pointer index member. Ideal code:

FUNCTION_BLOCK Exe_PalletShuttle EXTENDS Frame.Base_LocalScope
VAR
    {attribute 'hide'}pointer_Step: POINTER TO Frame.Base_Step;
    {attribute 'hide'}step_Start: Frame.Base_Step;

    {attribute 'hide'}step_StartRecharg: Frame.Base_Step;

    {attribute 'hide'}step_LengthwaysMove_Start: Frame.Base_Step;
    {attribute 'hide'}step_LiftShuttleCyd_PutDown: Frame.Base_Step;
    {attribute 'hide'}step_LengthwaysMove_GoTarget: Frame.Base_Step;
    {attribute 'hide'}step_LengthwaysMove_End: Frame.Base_Step;

   {attribute 'hide'}step_WidthwaysMove_Start: Frame.Base_Step;
    {attribute 'hide'}step_LiftShuttleCyd_Uplift: Frame.Base_Step;
    {attribute 'hide'}step_WidthwaysMove_GoTarget: Frame.Base_Step;
    {attribute 'hide'}step_WidthwaysMove_End: Frame.Base_Step;

    {attribute 'hide'}step_UpliftPallet_Start: Frame.Base_Step;
    {attribute 'hide'}step_LiftPalletCyd_Uplift: Frame.Base_Step;
    {attribute 'hide'}step_UpliftPallet_End: Frame.Base_Step;   

    {attribute 'hide'}step_PutdownPallet_Start: Frame.Base_Step;
    {attribute 'hide'}step_LiftPalletCyd_Putdown: Frame.Base_Step;
    {attribute 'hide'}step_PutdownPallet_End: Frame.Base_Step;  

   {attribute 'hide'}step_End: Frame.Base_Step;

   {attribute 'hide'}VividerMark: BOOL;

   {attribute 'hide'}obj_PalletLiftCyd: Frame.Device_Actuator;
    {attribute 'hide'}obj_DiverterLiftCyd: Frame.Device_Actuator;
END_VAR

pointer_Step:= ADR(step_Start); InitialStepScope(FirstAdr:=pointer_Step ); Feeling the current mechanism of pointer implementation, such a function seems to be difficult to achieve. Looking forward to the launch of the collection function.

Alex Samrt
  • 21
  • 2

1 Answers1

0

You can't know the type of the data the pointer points to. When you create the pointer, you are explicitly telling the compiler to assume the data is of the specified type.

You could store the address of the first and last elements and iterate between them (haven't tested):

elem1: MY_STRUC;
elem2: MY_STRUC;
...
elemN: MY_STRUC;

pbegin: POINTER TO MY_STRUCT := ADR(elem1);
pend: POINTER TO MY_STRUCT := ADR(elemN);

WHILE pbegin <> pend DO
    // use pbegin^
    pbegin := pbegin + SIZEOF(pbegin^); // or pbegin := ADR(pbegin[1]);
END_FOR

However, the above assumes that:

  • All of elemX are of the same size
  • There are no other type of variables in between the elements
  • Sequentially defined variables in CODESYS must also be placed in memory sequentially in the same order (don't know if this is true)

As such, the above is very error prone in my opinion. A better approach might be to "bundle" the elements in a dedicated structure (tested on a simulator):

TYPE MY_STRUC_BUNDLE:
STRUCT
    elem1: MY_STRUC;
    elem2: MY_STRUC;
    ...
    elemN: MY_STRUC;
END_STRUCT
END_TYPE

bundle: MY_STRUC_BUNDLE;
ptr: POINTER TO MY_STRUCT := ADR(bundle);
len: UDINT := SIZEOF(bundle) / SIZEOF(ptr^) - 1;
index: UDINT;

FOR index := 0 TO len DO
    // use ptr[Index]
END_FOR

Assuming that the bunle structure only contains the desired structs of the same type (and size), this should work as structures should have a continuous memory segment.

I still think that if you want to access normal variables with an index, the best, and least error prone, solutions is to bind them into an array:

elem1: MY_STRUC;
elem2: MY_STRUC;
...
elemN: MY_STRUC;

arr: ARRAY [1..N] OF POINTER TO MY_STRUC := [ADR(elem1), ADR(elem2), ..., ADR(elemN)];

FOR Index := 1 TO N DO
    // use arr[Index]^
END_FOR
Guiorgy
  • 1,405
  • 9
  • 26