如何在codesys/twincat3中传递扩展类型的数组?



假设我有一个抽象的功能块AValve,我扩展了各种类型的阀门。我将AValve扩展为BasicValve来实现它。我还有一个函数块,它接受AValve数组,看起来像这样

FUNCTION_BLOCK ValveDispatch
VAR_IN_OUT
valves : ARRAY[*] OF AVALVE;
END_VAR

如果我试图传递一个BasicValve数组到这个函数块,我遇到了:

无法转换类型'ARRAY [0..][5]

返回VAR_IN_OUT ' values '的值

认为也许codesys只是不能同时处理扩展类型和可变长度数组,我试过做一个集合长度数组作为输入,只是为了测试,因为我需要可变长度。这样做会产生一个稍微不同的错误,但似乎意味着相同的事情:

类型的数组(0 . .[5]的BasicValve'不等于类型'ARRAY [0..][5] OF valve ' OF VAR_IN_OUT ' values

我有办法让这个工作吗?将单个扩展对象传递到期望其基类型的输入中可以正常工作,但似乎不支持对数组这样做。

您看到的问题实际上可以归结为一个非常简单的点,数组是值数据类型.

也就是说,当你试图通过VAR_IN_OUT传递ARRAY [*] OF FB_Ext时,你实际上是在创建一个全新的数据类型ARRAY [*] OF FB_Ext,它不扩展ARRAY [*] OF FB_Base

如果你在ST中查看位级别的数组,问题变得非常清楚,数组本身的大小为ElementSize * ElementCount,因此试图将更大的数据类型FB_Ext强制到FB_Base的较小数据空间中是不可能在不搞砸一切的情况下工作的。

所以你必须用指针或接口来做这个处理。


TLDR:你想做的事在st是不可能的

这本来是一个注释,但是它有点超出了大小限制。作为wiki发布

简短的回答:对于Var_In_Out,这是不可能的。Var_in_out是一种引用调用。在TwinCAT中,引用总是有严格的类型绑定。

我的第一种方法是用简单的var_input接口指针来解决这个问题。接口包含您所移交的字段的大小和类型(如Array[*]所做的)。但我不确定是否允许派生接口指针切换。也许你必须移交基本接口,并在某个地方手动与__TCQUERYINTERFACE进行接口转换。

我将在这里为我自己的问题添加一个答案,但暂时不接受它,以防有人有秘密要泄露,哈哈。

实际上,据我所知,将Array of Derived Type传递给Array of BasicType的模式根本不受支持。通过VAR_IN_OUT或其他输入类型。你甚至不能把一个分配给另一个。最好我能告诉Codesys不尊重继承时比较数组彼此,但将如果你比较数组的一个特定的索引到一个对象。我想出了两种我不喜欢但应该可行的方法。

如果你要传递接口,你可以像这样在调用函数块的头文件中构建数组:

VAR
aFB : ARRAY[0..2] of ExtendedFB;//implements IExtended, which extends IBasic
aInterface : ARRAY[0..2] OF IBasic := [aFB[0], aFB[1],aFB[2]];
END_VAR

当涉及到扩展fb而不是接口时,这将不太有效。在这种情况下,我必须使用指针,像这样:

VAR
aFB: ARRAY[0..2] of ExtendedFB;//extends AbstractFB
apFB : Array[0..2] of Pointer to AbstractFB := [ADR(afb[0]), ADR(afb[1]), ADR(afb[2])];
END_VAR

TL;DR不是将Array of ExtendedType传递到期望Array of BasicTypeReference to Array of BasicType的输入,您可以使用ExtendedType对象手动构建Array of BasicType,每次一个索引并传递它,而不会引起编译器的抱怨。不幸的是,如果不使用接口,就只能使用指针,因为如果不实例化函数块,就不能创建函数块数组。

最新更新