使用Codesys v2.3,我试图制作一个功能块来检查指针数据的大小,以免超出此范围而不会写入内存的一部分。
例如:
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^);
现在,如果我将BYTE的地址放入该块的pData中,则IF仍将检出,因为取消引用的指针似乎只返回我们指向的大小(在这种情况下为REAL)。
我知道有可能需要输入大小,但是如果错过或输入错误,可能会出现潜在问题,因为它会以其他方式干扰程序
是否有一种方法可以检查所指向的数据的大小,同时避免外部输入?
答案 0 :(得分:0)
据我所知,无法检测到指针的数据类型是什么,因为它只是一个内存地址。如您所说,您应该提供指针目标的大小作为其他参数。只需添加一个指针不为零且大小不为零的检查,以防止出现(某些)问题。
其他环境的解决方案:
对于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^)
);
这也许有点题外话,对此感到抱歉,希望对您有所帮助。仍然希望有人会知道更好的解决方案。
编辑 实际上找到了其他很棒的解决方案,但我认为它也仅适用于TwinCAT3。我也想将其发布在这里。
通过使用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^
);
答案 1 :(得分:0)
为什么在此功能已经存在的情况下,为什么需要这种功能来检测可变大小?
您要做的就是直接在程序内部调用NewUserOperation
。您不需要使用指针。据我了解,您之所以使用它们,是因为您想使输入变量具有任何类型的通用性,而不是因为您在程序中使用了指针。因此,所有原始变量都直接分配。
您的函数尝试创建SIZEOF()
的环绕,而无需更改计算算法中的任何内容,然后仅使用SIZEOF()
,因为这是该函数的作用。
告诉我为什么您尝试创建单独的功能,而我 会相应地更改答案。
我的假设是您需要检查变量是否是所需的大小。然后,您可以创建一个函数。
SIZEOF()
然后您可以这样称呼
FUNCTION IsSize : BOOL
VAR_INPUT
VarSize: INT;
CompareTo: INT;
END_VAR
IsSize := (VarSize = CompareTo);
END_FUNCTION
编辑:使用数组
如果您要创建与数组一起使用的函数,并且希望能够传递无限数量的元素数组,则可以这样做。
VAR
MyVar: REAL;
END_VAR
IF IsSize(SIZEOF(MyVAR), 4) THEN
// DO something
END_IF
然后输入您可以的代码
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