Variant (C)
DarraUa_Variant* 是 OPC UA 的通用值容器, 覆盖 OPC UA 全部内置数据类型. SDK 用它在 C 与 Stack 之间传值.
配套
- 包装值 + 时间戳 + 状态请看 DataValue.
- 标准节点常量请看 WellKnownNodes.
公共 API
| 类别 | 属性 | 类型 | 访问 | 说明 |
|---|---|---|---|---|
| 生命周期 | DarraUa_Variant_New() | DarraUa_Variant* | RW | 新建空 Variant; 用 _Delete 释放 |
DarraUa_Variant_Delete(v) | void | W | 释放 Variant 句柄 (v 为 NULL 时安全) | |
| 类型 / 状态 | DarraUa_Variant_GetType(v) | DarraUa_BuiltinType | R | 内置类型枚举 |
DarraUa_Variant_IsScalar(v) | int32_t | R | 1 = 标量, 0 = 数组 | |
DarraUa_Variant_IsArray(v) | int32_t | R | 1 = 数组 | |
DarraUa_Variant_GetArrayLength(v) | int32_t | R | 数组长度, -1 = 标量 |
标量 Set / Get
DarraUa_Variant* v = DarraUa_Variant_New();
DarraUa_Variant_SetBoolean(v, 1); /* 1 = true */
DarraUa_Variant_SetByte(v, 255);
DarraUa_Variant_SetInt16(v, 42);
DarraUa_Variant_SetInt32(v, 42);
DarraUa_Variant_SetUInt32(v, 42u);
DarraUa_Variant_SetInt64(v, 42LL);
DarraUa_Variant_SetFloat(v, 3.14f);
DarraUa_Variant_SetDouble(v, 3.14);
DarraUa_Variant_SetString(v, "hello");
DarraUa_Variant_SetDateTime(v, 132680064000000000LL); /* 100ns since 1601 */
/* Get */
int32_t b = 0; DarraUa_Variant_GetBoolean(v, &b);
int32_t i = 0; DarraUa_Variant_GetInt32(v, &i);
double d = 0.0; DarraUa_Variant_GetDouble(v, &d);
const char* s = DarraUa_Variant_GetString(v); /* 内部指针, 不释放 */
DarraUa_DateTime ts = DarraUa_Variant_GetDateTime(v);
DarraUa_Variant_Delete(v);
每个 Set* 返回 int32_t: 1 = OK, 0 = 类型不匹配 / 失败. 每个 Get* 返回 1 表示成功写入, 类型不符返回 0 不修改 out 参数.
QualifiedName / LocalizedText
/* QualifiedName */
DarraUa_Variant_SetQualifiedName(v, /*ns*/ 2, "Counter");
uint16_t ns = 0; const char* name = NULL;
DarraUa_Variant_GetQualifiedName(v, &ns, &name); /* name 生命周期 = v */
/* LocalizedText */
DarraUa_Variant_SetLocalizedText(v, "zh-CN", "温度");
const char* loc = NULL; const char* text = NULL;
DarraUa_Variant_GetLocalizedText(v, &loc, &text);
数组 Set / Get
double arr[] = { 1.0, 2.0, 3.0 };
DarraUa_Variant_SetDoubleArray(v, arr, 3);
int32_t len = DarraUa_Variant_GetArrayLength(v); /* 3 */
double out[16] = {0};
DarraUa_Variant_GetDoubleArray(v, out, 16);
/* 字符串数组 */
const char* names[] = { "a", "b", "c" };
DarraUa_Variant_SetStringArray(v, names, 3);
const char* one = DarraUa_Variant_GetStringArrayItem(v, 0); /* 内部指针, 不释放 */
支持的数组类型 (深拷贝, Variant 自管释放):
DarraUa_Variant_SetBooleanArray(v, ints, n);
DarraUa_Variant_SetInt32Array (v, ints, n);
DarraUa_Variant_SetUInt32Array (v, uints, n);
DarraUa_Variant_SetInt64Array (v, i64s, n);
DarraUa_Variant_SetFloatArray (v, fs, n);
DarraUa_Variant_SetDoubleArray (v, ds, n);
DarraUa_Variant_SetStringArray (v, strs, n);
Get*Array 当 out_capacity < length 时不拷贝, 返回所需 length, 调用方扩容再调一次.
BuiltinType 完整清单
typedef enum {
DARRA_UA_TYPE_NULL = 0,
DARRA_UA_TYPE_BOOLEAN = 1,
DARRA_UA_TYPE_SBYTE = 2,
DARRA_UA_TYPE_BYTE = 3,
DARRA_UA_TYPE_INT16 = 4,
DARRA_UA_TYPE_UINT16 = 5,
DARRA_UA_TYPE_INT32 = 6,
DARRA_UA_TYPE_UINT32 = 7,
DARRA_UA_TYPE_INT64 = 8,
DARRA_UA_TYPE_UINT64 = 9,
DARRA_UA_TYPE_FLOAT = 10,
DARRA_UA_TYPE_DOUBLE = 11,
DARRA_UA_TYPE_STRING = 12,
DARRA_UA_TYPE_DATETIME = 13,
DARRA_UA_TYPE_GUID = 14,
DARRA_UA_TYPE_BYTESTRING = 15,
DARRA_UA_TYPE_XML_ELEMENT = 16,
DARRA_UA_TYPE_NODE_ID = 17,
DARRA_UA_TYPE_EXPANDED_NODE_ID = 18,
DARRA_UA_TYPE_STATUS_CODE = 19,
DARRA_UA_TYPE_QUALIFIED_NAME = 20,
DARRA_UA_TYPE_LOCALIZED_TEXT = 21,
DARRA_UA_TYPE_EXTENSION_OBJECT = 22,
DARRA_UA_TYPE_DATA_VALUE = 23,
DARRA_UA_TYPE_VARIANT = 24,
DARRA_UA_TYPE_DIAGNOSTIC_INFO = 25
} DarraUa_BuiltinType;
内存所有权
DarraUa_Variant* 是 opaque pointer, 由 Stack pool 管理:
| 来源 | 释放 |
|---|---|
DarraUa_Variant_New() | DarraUa_Variant_Delete(v) |
DarraUa_Session_Call(...) 输出数组的每项 | DarraUa_VariantArray_Delete(arr, count) (一次性) |
DarraUa_DataValue_GetValue(dv) 返回的 const DarraUa_Variant* | 不要释放 (生命周期 = dv) |
DarraUa_Variant_GetString / _GetStringArrayItem 返回的 const char* 是 Variant 内部缓冲, 不要 free. 想保留请 strdup.
ToString (打印)
C 没有自动 ToString, 自己根据 type 打印:
static void print_variant(const DarraUa_Variant* v)
{
if (!v || DarraUa_Variant_GetType(v) == DARRA_UA_TYPE_NULL) {
printf("(null)"); return;
}
switch (DarraUa_Variant_GetType(v)) {
case DARRA_UA_TYPE_DOUBLE: {
double d = 0.0; DarraUa_Variant_GetDouble(v, &d);
printf("%g", d); break;
}
case DARRA_UA_TYPE_INT32: {
int32_t i = 0; DarraUa_Variant_GetInt32(v, &i);
printf("%d", (int)i); break;
}
case DARRA_UA_TYPE_STRING:
printf("\"%s\"", DarraUa_Variant_GetString(v)); break;
case DARRA_UA_TYPE_DATETIME:
printf("ft=%lld", (long long)DarraUa_Variant_GetDateTime(v)); break;
default:
printf("<type %d>", (int)DarraUa_Variant_GetType(v));
}
}