Как создать указатель на функцию в CodeSy v3

Можете ли вы дать мне пример того, как я могу объявить указатель на функцию в моей библиотеке? И как я могу передать указатель на функцию к моей внешней библиотеке?

4 ответа

TL;DR: Сумки возможны и очень легко в CoDeSys v3.

В CoDeSys "функции" - это на самом деле указатели на функции, хранящиеся в таблице функций.

В CodeSys v2, чтобы получить адрес функции, вы должны были использовать INDEXOF(F_MyFunction), и это обеспечило индекс указателя функции в таблице функций. Получение адреса стола было, ммм, упражнением для читателя (его можно было найти с помощью некоторой гимнастики).

В CoDeSys v3, ADR работает вместо INDEXOF, и поэтому ADR(F_MyFunction) дает вам адрес указателя функции, который указывает на F_MyFunctionкод!

И угадайте, что: вы можете установить этот указатель на функцию и F_MyFunction(...) это просто вызов через указатель на функцию.

Это так просто.

Итак, чтобы выполнять косвенные вызовы функций, все, что вам нужно сделать, это объявить фиктивную "функцию", которая в действительности работает как устанавливаемый указатель на функцию!

Предположим, у нас есть две целевые функции, которые мы хотим вызвать косвенно:

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

Затем мы определяем "указатель на функцию", который должен иметь ту же сигнатуру, что и косвенно вызываемые функции:

FUNCTION FPTR_Add : INT
VAR_INPUT
  param : INT;
END_VAR
END_FUNCTION

У нас также может быть помощник, который назначает указатели на функции:

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

Наконец, давайте сделаем несколько косвенных вызовов:

// 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

Единственным недостатком этого метода является то, что отладчик не проверяет динамические значения указателей на функции и, таким образом, шаг внутрь ведет себя как шаг вперед. Обходной путь состоит в том, чтобы установить точку останова в целевых функциях, после чего оба шага и переход остановятся на этом.

Есть и другие способы достижения этого эффекта, например, путем прямого управления фреймами стека, поэтому даже если этот точный метод перестанет работать из-за некоторых изменений в CoDeSys, есть другие способы сделать это.

Это старая тема, но, похоже, есть другой (намного лучший) способ обойти отсутствующую функцию указателя функции. Т.е. используя указатель на функциональный блок и вызывая его метод, см. код ниже.

      FUNCTION_BLOCK TButtonHandlers
//with
METHOD Click : BOOL
METHOD LongClick : BOOL

и

      PROGRAM FOO
VAR
  Handlers: TButtonHandlers;
  pHdl: POINTER TO TButtonHandlers; 
END_VAR
-
pHdl:= ADR(Handlers); //Assign
pHdl^.Click(); //Function Call

Надеюсь, это поможет таким людям, как я, наткнуться на эту (старую) тему.

Указатели возможны в codesysСоздать указатель в codesys ты бы сделал

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

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

разыменовать этот указатель вы бы

derefereceVar := tempVar^;

Поэтому, если вы хотите иметь указатель в качестве аргумента вашей функции, вы должны передать pVar или же ADR(tempVar) в приведенном выше примере для параметра вашей функции, который принимает POINTER_TO_BYTE как тип.

На платформах Codesys можно создать указатель на тип данных или функциональный блок. В TwinCAT 3 также возможно создать указатель на функцию, но он не может быть вызван в программе ПЛК. Указатель функции может быть задан только как параметр внешнего компонента библиотеки.

Проверьте это: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/136447627.html&id=4296747249216071915

Другие вопросы по тегам