跳到主要内容

Darra OPC UA Client — C++ SDK

Darra OPC UA Client C++ 绑定. header-only, C++17, RAII, 命名空间 darra::opcua. API 命名 / 行为与 C# 完全对齐, 学一种全语言可用.

章节导航

安装

C++ SDK 是 header-only, 不需要单独编译 .cpp. 把 Darra_OPCUA_ClassLibrary/CPP/include/ 加到工程 include 路径, 并 link 底层 C 实现 darra_opcua 即可.

add_executable(my_app main.cpp)

target_include_directories(my_app PRIVATE
${CMAKE_SOURCE_DIR}/third_party/Darra_OPCUA_ClassLibrary/CPP/include
${CMAKE_SOURCE_DIR}/third_party/Darra_OPCUA_ClassLibrary/C/include)

target_link_libraries(my_app PRIVATE darra_opcua)
target_compile_features(my_app PRIVATE cxx_std_17)

系统要求

要求
编译器C++17 (MSVC 2019+, GCC 8+, Clang 10+)
OSWindows 10/11, Windows Server 2019+, Linux (Ubuntu 20.04+)
平台x64
协议OPC UA TCP (opc.tcp://)

命名空间

#include <darra/opcua/client.hpp>           // Session / Variant / DataValue / Subscription
#include <darra/opcua/discovery.hpp> // Discovery::GetEndpoints / FindServers
#include <darra/opcua/history.hpp> // HistoryAggregate / HistoryUpdateType
#include <darra/opcua/well_known_nodes.hpp> // 标准节点常量

using namespace darra::opcua;

主要类型:

C++ 类型C# 对应用途
darra::opcua::SessionDarraOpcUaClient 主类 (一个 Session)
darra::opcua::SubscriptionOpcUaSubscription数据订阅容器
darra::opcua::EventSubscriptionOpcUaEventSubscription事件订阅 (Alarms & Conditions)
darra::opcua::NodeCollection / NodeNodeCollection / OpcUaNodeLazy Load 节点访问
darra::opcua::Variant / DataValue同名数据封装
darra::opcua::Discovery (静态)同名GetEndpoints / FindServers
darra::opcua::WellKnownNodes (静态)同名OPC Foundation 标准节点常量
darra::opcua::ExceptionOpcUaException携带 StatusCode 的异常

一分钟快速开始

#include <darra/opcua/client.hpp>
#include <iostream>

using namespace darra::opcua;

int main() {
Stack::Init(); // 全局初始化
Session s("opc.tcp://localhost:4840"); // RAII, 栈对象
s.Connect();

// 读
auto dv = s.Read("ns=2;s=Temperature");
std::cout << "Temperature = " << dv.Value().AsString() << " degC\n";

// 写
Variant v; v.SetDouble(42.0);
s.Write("ns=2;s=Setpoint", v);

// 订阅
auto sub = s.CreateSubscription(500.0);
sub.AddNode("ns=2;s=Counter", [](DataValue const& dv) {
std::cout << "Counter = " << dv.Value().AsString() << "\n";
});

Stack::Shutdown();
return 0;
}

高级 API 概览

功能入口 API说明
连接 / 加密Session(...) + s.Connect()None / Sign / SignAndEncrypt + Username / Anonymous / Certificate
单点读写s.Read / s.Write单节点单 Attribute
批量读s.ReadMany(node_ids[, attr])一次 RPC, N 节点
浏览树s.Browse / BrowseMany / BrowseWithPaging / BrowseNext完整分页支持
路径解析s.Resolve / TranslateBrowsePaths浏览路径 → NodeId
注册节点s.RegisterNodes / UnregisterNodes高频访问加速 30-50%
数据订阅s.CreateSubscription + sub.AddNode / AddManypublishing / sampling 双层
事件订阅s.SubscribeEvents报警 & 条件
调方法s.Call(obj_id, mtd_id, inputs)OPC UA Method 节点
历史读s.ReadHistory / ReadHistoryModified / AtTime / Processed / Events5 模式
历史写s.UpdateHistory / DeleteHistoryRangeInsert / Replace / Update / Delete
心跳s.SetKeepAliveInterval(ms)后台周期探测
自动重连(内置, 由 ConnectionConfig.auto_reconnect 控制)检测断线 → Republish 订阅
统一事件s.Events().on_*会话 / 订阅 / 数据 / 通讯异常
服务发现Discovery::GetEndpoints / FindServers不需要 Session

RAII 与异常

C++ SDK 全部资源都是 RAII, 栈对象自动管理生命周期, 不要 new, 析构自动释放. 错误统一抛 darra::opcua::Exception, 含 status_code() / status() 方法:

try {
Session s("opc.tcp://localhost:4840");
s.Connect();
auto dv = s.Read("ns=2;s=NotExist");
} catch (Exception const& ex) {
std::cerr << "OPC UA error: " << ex.what()
<< " status=0x" << std::hex << ex.status_code() << std::dec << "\n";
if (ex.status() == Status::BadNodeIdUnknown) { /* 处理 */ }
}

Move-only 语义

Session / Subscription / EventSubscription / Variant / DataValue 都不可拷贝, 但可 move (像 std::unique_ptr):

Session s1("opc.tcp://localhost:4840");
// Session s2 = s1; // 编译错误: copy ctor deleted
Session s2 = std::move(s1); // OK, s1 此后失效

防止重复释放 native handle.

FileTime 时间约定

历史 API 时间一律用 FileTime (UTC 100ns since 1601-01-01), 与 Windows DateTime.ToFileTimeUtc() 一致:

constexpr int64_t WIN_EPOCH_OFFSET = 116444736000000000LL;  // 1601 → 1970 间隔

auto now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
int64_t now_ft = WIN_EPOCH_OFFSET + now_ns / 100;

跨语言对齐

C# SDK 是参考实现, C++ 命名 / 参数 / 行为完全对齐. C# ua.Read(...) ↔ C++ s.Read(...) ↔ Python ua.read(...). 选 C++ 后切其他语言时只需查 跨语言映射.

按左侧侧边栏顺序读完即可掌握全部 SDK API.