3

Can you give me an example of how can I declare a pointer to function in my library? And how can I pass a pointer to function to my external library?

Kenster
  • 23,465
  • 21
  • 80
  • 106
Ksouri Wissem
  • 49
  • 1
  • 5

3 Answers3

6

TL;DR: Totes possible and dead easy in CoDeSys v3.

In CoDeSys, "functions" are really function pointers stored in a function table.

In CodeSys v2, to take the address of a function you had to use INDEXOF(F_MyFunction), and this provided the index of the function pointer in the function table. Getting the address of the table was, uh, an exercise for the reader (it was possible to retrieve it with some gymnastics).

In CoDeSys v3, ADR works instead of INDEXOF, and thus ADR(F_MyFunction) gives you the address of the function pointer that points to F_MyFunction's code!

And guess what: you can set that function pointer, and F_MyFunction(...) is just a call through that function pointer.

It's that simple.

So, to do indirect function calls, all you need to do is to declare a dummy "function" that in reality works like a settable function pointer!

Suppose we have two target functions that we want to call indirectly:

FUNCTION F_Add1: INT
VAR_INPUT
  param : INT;
END_VAR
F_Add1:= param + 1;
END_FUNCTION

FUNCTION F_Add2: INT
VAR_INPUT
  param : INT;
END_VAR
F_Add2:= param + 2;
END_FUNCTION

We then define a "function pointer" that must have the same signature as the indirectly called functions:

FUNCTION FPTR_Add : INT
VAR_INPUT
  param : INT;
END_VAR
END_FUNCTION

We can also have a helper that assigns to function pointers:

F_FPTR_Assign
VAR_INPUT
  dst : POINTER TO PVOID;
  src : POINTER TO PVOID;
END_VAR
dst^ := src^;
END_FUNCTION

Finally, let's do some indirect calls:

// should return 3 if indirect calls work
FUNCTION F_Test : INT
VAR
  val : INT;
END_VAR

F_FPTR_Assign(ADR(FPTR_Add), ADR(F_Add1));

// FPTR_Add points to F_Add1
val := FPTR_Add(val);
// here val has value 1

F_FPTR_Assign(ADR(FPTR_Add), ADR(F_Add2));

// FPTR_Add points to F_Add2
val := FPTR_Add(val);
// here val has value 3

F_Test := val;

END_FUNCTION

The only drawback of this method is that the debugger doesn't examine the dynamic values of function pointers and thus step into behaves like step over. The workaround is to set the breakpoint in the targeted functions, then both step into and step over will stop there.

There are other ways of achieving this effect, e.g. by direct manipulation of the stack frames, so even if this exact method would stop working due to some changes in CoDeSys, there are other ways of doing it.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thank you so much. This also worked flawlessly in Beckhoff's TwinCat3! – dotKokott Sep 24 '20 at 13:28
  • @dotKokott You may want to contact your Beckhoff reps and tell them that the need for such gymnastics is not acceptable in this day and age. Function pointers or equivalents are a basic functionality of any modern programming system, and the fact that TC3 does not officially support them is like a slap in the face. There needs to be solid pressure from the software engineering community on vendors like CoDeSys and Beckhoff whose development tools are stuck in the 2nd half of the last century. They won't improve anything if all they hear is crickets. We need change. Please do contact them. – Kuba hasn't forgotten Monica Sep 24 '20 at 16:37
  • Does this work with function block methods? – TheColonel26 Aug 20 '22 at 14:23
  • @Kubahasn'tforgottenMonica I do not understand why you think TC3 and Codesys 3.5 old. Compared to any other PLC development platform, they are leaps and bounds better than Rockwell, Siemens Etc. Yeah codesys is very behind modern software development, but for PLC code development it is cutting edge. Why PLC platforms are better? – TheColonel26 Sep 01 '22 at 17:17
-1

Pointers are possible in codesys.To create a pointer in codesys you would do

VAR 
  pVar : POINTER TO BYTE;
  tempVar  : BYTE;
  derefereceVar : BYTE;
END_VAR

//get a pointer to the byte variable
pVar := ADR(tempVar);

to dereference that pointer you would

derefereceVar := tempVar^;

So if you wanted to have a pointer as an argument to your function you would pass in pVar or ADR(tempVar) in the example above to a parameter of your function that takes a POINTER_TO_BYTE as the type.

mrsargent
  • 2,267
  • 3
  • 19
  • 36
  • thank you for your reply,but I like to create pointer to function for example in c languge we do like this :int sum (int num1, int num2) { return sum1+sum2; } int main() { int (*f2p) (int, int); f2p = sum; int op1 = f2p (10, 13); int op2 = sum (10, 13); printf("Output 1 – for function call via Pointer: %d",op1); printf("Output2 – for direct function call: %d", op2); return 0; } so I like to do the same in codesys to send this pointer to myexternal library – Ksouri Wissem Mar 31 '17 at 14:20
-1

Edit 09/2020: See the another answer in this topic and forget this one!

In Codesys based platforms it is possible to create a pointer to a data type or a function block. In TwinCAT 3 it is also possible to create a function pointer, but it can't be called in PLC program. The function pointer can only be given as a paramter to an external library component.

Check this: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/136447627.html&id=4296747249216071915

Quirzo
  • 1,183
  • 8
  • 10
  • Just noticed that I have received few downvotes for this answer. Just wondering if there is something wrong by answering the question. You can't make function pointers in PLC code of Codesys 3. – Quirzo Feb 23 '18 at 12:18
  • But you can, and ADR is how you do it - nothing in ADR's documentation that you linked to is contrary to that. They don't document what comes out of ADR, i.e. how to use it. That's left to one's own travails, but is easy to figure out. You're running in 32- or 64-bit kernel mode, with flat memory, and the world is wide open, so to speak. No big deal investigating the memory contents at all. – Kuba hasn't forgotten Monica Sep 24 '20 at 16:41
  • Thanks for your answer to this topic, it's inspiring! – Quirzo Sep 25 '20 at 07:36