MethodBuilder
概述
OPC UA Call 服务 (Part 4 §5.11.2) 要求把入参打包成 Variant[]。DarraUa_MethodBuilder_* 提供链式 C API, 自动按类型选 Variant 编码。
API
| 函数 | 类别 | 读写 | 说明 |
|---|---|---|---|
| DarraUa_MethodBuilder_New(ua, obj, mid, &out_b) | 构造 | — | 绑定到方法 |
| DarraUa_MethodBuilder_Free(b) | 释放 | — | 析构 |
| DarraUa_MethodBuilder_LoadInputArgs(b) | 链式 | 读 | 读 InputArguments 描述 |
| DarraUa_MethodBuilder_ArgByName(b, name, value) | 链式 | — | 按名设值 |
| DarraUa_MethodBuilder_ArgByIndex(b, index, value) | 链式 | — | 按索引设值 |
| DarraUa_MethodBuilder_Invoke(b, &out_outs, &out_n) | 终端 | 写 | 调用, 返回 StatusCode |
value 是 DarraUa_Variant*, 用 DarraUa_Variant_Set* 系列填充。
代码示例
#include <opcua.h>
int main() {
DarraUa_Session* ua;
DarraUa_Session_New("opc.tcp://localhost:4840", &ua);
DarraUa_Session_Connect(ua);
// 1) 流式调用
DarraUa_MethodBuilder* b;
DarraUa_MethodBuilder_New(ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo", &b);
DarraUa_MethodBuilder_LoadInputArgs(b);
DarraUa_Variant vx, vy, vs;
DarraUa_Variant_SetDouble(&vx, 100.0);
DarraUa_Variant_SetDouble(&vy, 200.0);
DarraUa_Variant_SetInt32(&vs, 50);
DarraUa_MethodBuilder_ArgByName(b, "x", &vx);
DarraUa_MethodBuilder_ArgByName(b, "y", &vy);
DarraUa_MethodBuilder_ArgByName(b, "speed", &vs);
DarraUa_Variant* outs = NULL;
size_t n_outs = 0;
DarraUa_StatusCode st = DarraUa_MethodBuilder_Invoke(b, &outs, &n_outs);
if (st != UA_GOOD) fprintf(stderr, "MoveTo 失败 0x%08X\n", st);
DarraUa_FreeVariants(outs, n_outs);
DarraUa_MethodBuilder_Free(b);
// 2) 按索引
DarraUa_MethodBuilder* b2;
DarraUa_MethodBuilder_New(ua, "ns=2;s=Calc", "ns=2;s=Calc.Add", &b2);
DarraUa_Variant a, c;
DarraUa_Variant_SetDouble(&a, 3.14);
DarraUa_Variant_SetDouble(&c, 2.71);
DarraUa_MethodBuilder_ArgByIndex(b2, 0, &a);
DarraUa_MethodBuilder_ArgByIndex(b2, 1, &c);
DarraUa_Variant* o2 = NULL;
size_t n2 = 0;
DarraUa_MethodBuilder_Invoke(b2, &o2, &n2);
double sum;
DarraUa_Variant_GetDouble(&o2[0], &sum);
printf("Add → %f\n", sum);
DarraUa_FreeVariants(o2, n2);
DarraUa_MethodBuilder_Free(b2);
DarraUa_Session_Free(ua);
return 0;
}
与 Call 的对比
// 旧写法: 手撸 Variant[]
DarraUa_Variant inputs[3];
DarraUa_Variant_SetDouble(&inputs[0], 100.0);
DarraUa_Variant_SetDouble(&inputs[1], 200.0);
DarraUa_Variant_SetInt32(&inputs[2], 50); // 类型?
DarraUa_Variant* outs;
size_t n;
DarraUa_Session_Call(ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo",
inputs, 3, &outs, &n);
// 新写法: MethodBuilder (类型由 ArgByName 内部记录)
DarraUa_MethodBuilder* b;
DarraUa_MethodBuilder_New(ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo", &b);
// ... ArgByName / Invoke
实现限制
- LoadInputArgs 依赖 ExtensionObject 解码
- 不支持复杂结构入参
- Invoke 失败返回
Bad*StatusCode, 不打印日志, 业务自己判读
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| MethodBuilder | MethodBuilder | MethodBuilder | MethodBuilder | MethodBuilder | DarraUa_MethodBuilder_* |
| .Arg(name, value) | .arg(name, value) | .arg(name, value) | .Arg(name, value) | .arg(name, value) | DarraUa_MethodBuilder_ArgByName |