Насколько я знаю, нет способа определить тип данных указателя, поскольку это просто адрес памяти. Вы должны указать размер указателя цели в качестве другого параметра, как вы сказали. Просто добавьте проверку, что указатель не равен нулю, а размер не равен нулю, чтобы предотвратить (некоторые) проблемы.
Решения для других сред:
Для TwinCAT 3 можно было бы создать решение с одним входом, используя T_Arg
и такие помощники, как F_INT
, но я думаю, что в Codesys 2 их нет (кто-нибудь подтверждает?). В этом решении вам в любом случае придется изменить вызов функции, чтобы указатель не был вводом.
В этом решении вы можете создать функцию с вводом T_Arg
. А затем вызовите его, используя вспомогательную функцию для каждого типа данных. От T_Arg
можно получить тип данных, размер и местоположение данных.
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
И назвать это:
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^)
);
Это, возможно, немного оффтоп, так что извините, надеюсь, это кому-нибудь поможет. Все еще надеемся, что кто-нибудь узнает лучшее решение.
EDIT
На самом деле нашел другое отличное решение, но я думаю, что это также только для TwinCAT 3. Просто хотел опубликовать его здесь тоже.
Используя тип данных ANY
, можно указать что угодно в качестве параметра и получить его размер. Разница в том, что он не примет POINTER
в качестве ввода.
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;
Использование:
//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
Test := PointerToReal^
);