You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C# ADS访问TwinCAT3中动态创建的子类对象变量

问题描述

我正在用TwinCAT3和C# ADS开发HMI项目,出于架构设计需要想使用TwinCAT的面向对象编程。但作为新手,我不知道怎么通过ADS句柄把嵌套子类对象连接到HMI。

父功能块代码:

//Example
FUNCTION_BLOCK FB_Parent
VAR
    iParentVariable: INT;
END_VAR

继承自父类的子功能块:

//Example
FUNCTION_BLOCK FB_Child EXTENDS FB_Parent
VAR
    iChildVariable: INT;
END_VAR

程序里定义了一个FB_Parent类型的数组,收到自定义HMI(C#)的初始化指令时,动态创建FB_Child对象:

// Example
fbChild := __NEW(FB_Child);
array[0] := fbChild^;
__DELETE(fbChild);

问题是在C# HMI里无法创建句柄访问子类变量:

client = new AdsClient
{
    Timeout = 500
};
client.Connect(parameters.AmsNetID, parameters.AdsPort);
handler = client.CreateVariableHandle("PRG_MAIN.arrConveyors[0].iChildVariable");

我试过两种修改数组定义的方式,但都没用:

  1. 使用POINTER OF FB_Parent
  2. 用接口替代父类

请问怎么在TwinCAT里继续用面向对象和动态对象创建,同时通过C# ADS访问子类变量?


解决方案

1. 避免值拷贝,改用指针数组存储动态对象

你当前代码里的array[0] := fbChild^是把FB_Child的值拷贝到FB_Parent类型的数组元素中,这会切片子类的特有属性(比如iChildVariable),导致ADS无法识别这些属性。正确做法是用指针数组存储对象引用:

首先定义指针数组:

VAR_GLOBAL
    arrConveyors: ARRAY[0..N] OF POINTER TO FB_Parent;
END_VAR

动态创建对象时,直接存储指针,不要做值拷贝,也不要立即调用__DELETE(否则对象会被销毁):

// 正确的动态创建逻辑
fbChild := __NEW(FB_Child);
arrConveyors[0] := fbChild; // 存储指针,不拷贝值
// 不要在这里调用__DELETE,对象需要保持存在以被HMI访问

2. ADS访问子类属性的正确路径

ADS访问指针指向的对象属性时,需要用^表示指针解引用。C#中的变量路径要修改为:

handler = client.CreateVariableHandle("PRG_MAIN.arrConveyors[0]^.iChildVariable");

3. 进阶:用接口实现类型安全的属性暴露

如果需要更严谨的类型检查,可以定义包含子类属性的接口,让子类实现该接口:

INTERFACE IChild
    VAR_OUTPUT
        iChildVariable: INT;
    END_VAR
END_INTERFACE

FUNCTION_BLOCK FB_Child EXTENDS FB_Parent IMPLEMENTS IChild
VAR
    iChildVariable: INT;
END_VAR

此时ADS访问路径和指针方式一致,既保留面向对象架构,又能明确暴露HMI需要访问的属性。

4. 关键注意事项

  • 动态创建的对象必须在程序生命周期内保持存在,不要提前__DELETE,否则ADS访问会报错。
  • 若要销毁对象,需先通知HMI停止访问,再调用__DELETE并将数组中的指针置为0。
  • TwinCAT ADS不支持直接的多态属性访问,必须通过指针解引用或接口明确定位子类属性。

内容的提问来源于stack exchange,提问作者Schupbach Loïc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:42:43