0

Using Codesys v2.3, I'm trying to make a function block that checks the size of the pointer data, as to not write to parts of the memory beyond this.
Ex:

VAR_INPUT
    pData:        POINTER TO REAL;    // Or pointer to WORD or ARRAY[1..x] ...
END_VAR
VAR_OUTPUT
    DataSize:     DWORD;
END_VAR

IF SIZEOF(pData^) <> 4 THEN 
    RETURN;
END_IF

DataSize := SIZEOF(pData^);

Now, if I were to put the adress of a BYTE into pData of this block, the IF would still check out, as the dereferenced pointer only seems to return the size of what we point at (REAL in this case).

I know it's possible to require the size as an input, but this could be a potential problem if it's missed or inputted wrong, as it would mess with the program in other ways

Is there a way to check the size of whatever data is pointed at, while avoiding external inputs?

Jabbl
  • 59
  • 7

2 Answers2

1

As far as I know, there is no way to detect what is the datatype of the pointer, as it's just a memory address. You should provide the size of the pointer target as other parameter, as you said. Just add a check that pointer is not zero and size is not zero to prevent (some) problems.


Solutions for other environments:


For TwinCAT 3 it would be possible to create one-input solution by using T_Argand helpers suchs as F_INT but I think Codesys 2 doesn't have them (confirmation anyone?). In that solution you would have to change the function call anyways so that pointer wouldn't be an input.

In that solution you could create a function with input of T_Arg. And then call it by using a helper function for each datatype. From T_Arg is possible to acquire data type, size and data location.

FUNCTION_BLOCK FB_Test
VAR_INPUT
    Test : T_arg;
END_VAR

Test.eType; //Data type
Test.cbLen; //Variable data length in bytes
Test.pData; //Pointer to data

And to call it:

test is an instance of FB_Test
//INT for example
//Now the cblen = 2
test(
    Test := F_INT(PointerToInt^) 
);

//REAL for example
//Now the cbLen = 4
test(
    Test := F_REAL(PointerToReal^) 
);

This is perhaps a little offtopic so sorry about that, hope it helps somebody. Still hoping that somebody would know a better solution.

EDIT Actually found other great solution, but I think it is also only for TwinCAT 3. Just wanted to post it here too.

By using ANY data type, it is possible to give anything as parameter and get it's size. The difference is that it won't accept POINTER as input.

FUNCTION_BLOCK FB_Test2
VAR_INPUT
    Test : ANY;
END_VAR
VAR_OUTPUT
    Size : DINT;
END_VAR
//diSize contains size of the input data type
size := Test.diSize;

Usage:

//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
    Test := PointerToReal^
);
Quirzo
  • 1,183
  • 8
  • 10
  • First it should not be a function block but function. Second we are talking about CoDeSys 2.3 and it does not support `ANY` or `ANY_NUM` datatypes. At least my instance does not. Third, variables are not an object in ST and you cannot `Test.diSize` on input variable unless it is structure `Test` with property `diSize`. – Sergey Romanov Jul 04 '18 at 04:52
  • Jabbi asked for a function block, that's why it is one. And its easier to debug function blocks than functions during runtime. But yes, this should be a function. I also mentioned that I think it is not supported by Codesys 2.3, did you read my answer before rushing to comment? And third: The `ANY` is converted to a structure, so `Test.diSize` works just like it was a struct. – Quirzo Jul 04 '18 at 05:59
  • Bro, cool down, I am just sharing my experience. I am not editing or deleting you answer. Just say what I think about it. I am sorry my comments contain some critics. But it is not critic in anger and hate. It is constructive critic. Instead of getting into defensive position, you could just say "thank you, Sergey for valuable input." – Sergey Romanov Jul 04 '18 at 07:44
  • Sad that no such option exist within CoDeSys 2, it would be really nice to have. As noted on a comment to Sergey, the "DataSize := SIZEOF(pData^);" should really be replaced with any other code, I realize it was a bad example. My thought with this is to make a function/block that can detect the size of the incoming data, and act accordingly. – Jabbl Jul 04 '18 at 16:02
0

Why do you need such a function, just to detect variable size, while this function already exists?

All you have to do is call SIZEOF() directly inside your program. You do not need to use pointers. As I understand you are using them because you want to make input variable universal of any type, not because you use pointers in your program. So original variables are all allocated directly.

Your function is an attempt to create a wrap around SIZEOF() without changing anything in calculation algorithm, then just use SIZEOF(), as this is what this function is there for.

Tell me why you try to create separate function and I ll change the answer accordingly.

My assumption that you need to check if variable is the size you need. Then you can make a function.

FUNCTION IsSize : BOOL
    VAR_INPUT
        VarSize: INT;
        CompareTo: INT;
    END_VAR
    IsSize := (VarSize = CompareTo);
END_FUNCTION

And then you can call it like this

VAR
    MyVar: REAL;
END_VAR

IF IsSize(SIZEOF(MyVAR), 4) THEN
    // DO something
END_IF

Edit: work with array

If you what to create a function that works with array and you want to be able to pass array of indefinite number of elements then you can this.

FUNCTION ArrSize : BOOL
    VAR_INPUT
        MyArr: POINTER TO ARRAY[0..1000] OF BOOL;
        ArrNum: INT; (* Number of array elements *)
        ArrStart: INT; (* First index of an array *)
    END_VAR
    VAR
        iCount : INT := 0;
    END_VAR

    FOR iCount := ArrStart TO ArrNum DO
        MyArr^[iCount] := TRUE;
    END_FOR
END_FUNCTION

Then in a code you can

VAR
    aTest: ARRAY[0..20] OF BOOL;
END_VAR

ArrSize(ADR(aTest), SIZEOF(aTest), 0);
Sergey Romanov
  • 2,949
  • 4
  • 23
  • 38
  • It's mostly thought of as a way to make a function block with a variable array input, so that a single function block can handle multiple cases. The example in my question is just that, an example. It's not meant as the full thing – Jabbl Jul 04 '18 at 15:44
  • I get it. I am changing my answer and add answer. – Sergey Romanov Jul 06 '18 at 05:52