C / C++ API 参考
- C SDK:
include/pnet.h+src/,直接链接DarraPnet.dll(或静态库),命名Pnet*(C PascalCase)+pnet_result_t错误码。 - C++ SDK:header-only
include/pnet.hpp,命名空间darra::pnet。含两种形态:- 服务模式(推荐):
PnetService单一入口,经 Pnet Service 内置 HTTP API(端口 18840 固定)连接,由服务承载从站运行(WinHTTP 转发,不直连 native DLL); - native 直连(备选):
PnetLibrary+PnetDevice(RAII),直接加载DarraPnet.dll。
- 服务模式(推荐):
单一 PROFINET 网口契约(audit-2026-08-11,用户裁定 2026-08-10):设备对外只开放一个 PROFINET 网口(工业现场常态)。网卡选择在 GUI / Service 配置层完成,服务侧单一权威 =
NetworkInterfaceName(读取链:环境变量DARRA_PNET_NIC> 运行配置 XML<Network/InterfaceName>> appsettings 出厂默认;驱动绑定 / pnal 绑定目标 / MAC 解析同源一致,无双配置歧义)。native 直连模式下PnetConfig.MainNetifName为栈绑定的唯一网口名;EnumerateInterfaces()仅作诊断/枚举用途。
#include "pnet.h"
C++:PnetService — 服务模式单一入口(推荐)
经服务 HTTP API(端口 18840 固定)连接服务,由服务承载从站运行;SDK 与 Web API 同层。启停(POST /api/start|stop)/ IO(GET|POST /api/io)全部经服务转发,不直连 native。
#include "pnet.hpp"
using namespace darra::pnet;
PnetService service;
service.Connect("127.0.0.1", PnetService::kDefaultPort); // 端口固定 18840
service.Start(); // POST /api/start
// 地址化读写(ETH 式地址,对齐 C# 基准)
service.WriteBool("I0.0", true); // 写输入位(设备 → 控制器)
service.WriteInt16("IW2", counter); // 写输入字(大端)
bool start = service.ReadBool("Q0.0"); // 读输出位(控制器 → 设备)
int16_t cmd = service.ReadInt16("QW0"); // 读输出字(大端)
auto io = service.GetIo(); // 服务端过程映像快照
service.Stop(); // POST /api/stop(幂等)
service.Close();
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
Connect(host, port, apiKey) | void | 设备 | 写 | 连接服务(仅本地回环 127.0.0.1 可达,audit-2026-08-10:服务未开放局域网监听;端口固定 18840;服务端配置 API 密钥后必传) |
kDefaultPort | uint16_t | 设备 | 只读 | 服务 HTTP API 固定端口 18840(编译期常量) |
Start() | void | 设备 | 写 | 启动从站(POST /api/start,由服务承载;失败如实抛 PnetException) |
Stop() | void | 设备 | 写 | 停止从站(POST /api/stop,幂等) |
Status() | PnetState | 设备 | 只读 | 服务端运行态(GET /api/status 映射) |
StatusEx() | PnetServiceStatus | 设备 | 只读 | 服务端运行态快照(GET /api/status 一次取回 state / connected / errorCode;用户裁定 2026-08-10:错误码是调用契约的一部分,SDK 必须透出服务端 connected / errorCode) |
IsConnected() / IsStarted() | bool | 设备 | 只读 | 会话 / 本地启动状态 |
ReadBool(address) / WriteBool(address, value) | bool / void | IO | 读写 | 位地址(I0.0 / Q0.0 / M1.6 / DB1.DBX0.0;Q 区只读,写抛异常) |
ReadInt16(address) / WriteInt16(address, value) | int16_t / void | IO | 读写 | 字地址(IW2 / QW2 / MW0 / DB1.DBW0,大端) |
ReadInt32(address) / WriteInt32(address, value) | int32_t / void | IO | 读写 | 双字地址(ID4 / QD4 / MD0 / DB1.DBD0,大端) |
GetIo() | pair<vector<uint8_t>, vector<uint8_t>> | IO | 只读 | 服务端过程映像快照(I 区 / Q 区) |
LastError() | const string& | 设备 | 只读 | 最近一次服务 HTTP 调用错误(成功调用后清空) |
C++ 服务模式运行态:
StatusEx()返回PnetServiceStatus(state/connected/error_code),connected= 是否已与 IO 控制器建立周期数据交换(GET /api/status 的connected原值),error_code= 最近一次错误码原值(0 = 无错误;非零 = pnet 栈错误码,语义见PnetRuntimeErrorCode:Ok=0 /ErrInit=-1 /ErrCfg=-2 /ErrThread=-3 /ErrRunning=-4 /ErrPdi=-5 /Unknown=-10000)。未识别值如实映射Unknown,原始值仍经error_code透传。
C++:PnetDevice — native 直连(备选)
PnetLibrary 加载 DarraPnet.dll,PnetDevice RAII 构造即持有原生栈,析构自动停止并释放:
#include "pnet.hpp"
using namespace darra::pnet;
PnetLibrary lib;
if (!lib.Load("DarraPnet.dll")) { /* 失败处理 */ }
PnetDevice device(lib);
device.Slave().SetStationName("darra-device-01");
device.Start(); // 启动数据交换
device.Io().ReadInput(); // 读输入(从站 → 控制器)
device.Io().WriteOutput({0x01, 0x02}); // 写输出(控制器 → 从站)
device.Stop();
| 成员 | 类型 | 类别 | 读写 | 说明 |
|---|---|---|---|---|
PnetLibrary::Load(path) | bool | 设备 | 静态 | 运行时加载 DarraPnet.dll(无需链接库) |
PnetDevice(lib) | PnetDevice | 设备 | 构造 | 构造即初始化 PROFINET 栈(析构自动停止并释放) |
Start() / Stop() | void | 设备 | 写 | 启动 / 停止数据交换(可再次 Start) |
Slave() | PnetSlave | 从站 | 只读 | 从站控制(站名 / IP / 状态) |
Io() | PnetIo | IO | 只读 | 过程数据(ReadInput / WriteOutput) |
Alarm() / Diag() / Config() | PnetAlarm / PnetDiag / PnetConfig | 各域 | 只读 | 报警 / 诊断 / 运行配置 |
C API(pnet.h,native 直连)
#include "pnet.h"
pnet_device_handle_t dev = NULL;
PnetDeviceCreate(&pdev_config, &dev); // 创建(pdev_config 含站点名/IP/周期)
PnetConfigLoad(dev, "device.xml"); // 加载运行配置 XML
PnetConfigApply(dev); // 应用到栈(槽位插拔 + IOCR)
PnetDeviceConnect(dev); // 连接网络,等待控制器建 AR
uint8_t input[2] = { 0xAA, 0x01 };
PnetIoSetInput(dev, 0, 1, 1, input, 2, PNET_IOXS_GOOD); // 设备 → 控制器
uint8_t output[8];
PnetIoGetOutput(dev, 0, 1, 1, output, 8, &out_ioxs, &new_data); // 控制器 → 设备
PnetDeviceDisconnect(dev);
PnetDeviceDestroy(dev);
| 模块 | 函数族 | 说明 |
|---|---|---|
| 设备 | PnetDeviceCreate / PnetDeviceDestroy / PnetDeviceConnect / PnetDeviceDisconnect / PnetDeviceGetState | 创建 / 销毁 / 连接 / 断开 / 状态(属性风格) |
| 从站 | PnetSlaveStart / PnetSlaveStop / PnetSlaveApplicationReady / PnetSlaveAbort / PnetSlaveSetProviderState | 启停 / 应用就绪 / 中止 / Provider 状态 |
| IO | PnetIoSetInput / PnetIoGetOutput / PnetIoGetInputIoxs / PnetIoSetOutputIoxs | 过程数据(默认槽位常量 PNET_SLOT_DEFAULT = 1) |
| 报警 | PnetAlarm* | 报警发送 / 确认 |
| 配置 | PnetConfigLoad / PnetConfigApply / PnetConfigGetSlotCount | 运行配置 XML 加载 / 应用 |
| 诊断 | PnetDiag* | 诊断 / 统计 |
C SDK 按名绑定(GetProcAddress)动态加载 DarraPnet.dll(PNET_DYNAMIC_LOAD)或静态链接(DarraPnet.lib)。所有调用返回 pnet_result_t(PNET_OK = 0 成功)。
连接复用与超时(E 节跨语言对齐):C / C++ 服务模式内部缓存 WinHTTP 会话/连接句柄,请求间复用底层 TCP 连接(对齐 C# 共享 HttpClient);断链自动重建;超时经 WinHttpSetTimeouts 显式设置(connect/read 统一 5 秒);C 响应缓冲 16 KB。地址对齐规则与 C# 基准一致:字 / 双字偏移即字节偏移,不强制 2 / 4 对齐(IW3 合法)。
完整示例(basic_service.cpp)
#include "pnet.hpp"
#include <cstdio>
using namespace darra::pnet;
int main() {
PnetService service;
service.Connect("127.0.0.1", PnetService::kDefaultPort);
service.Start();
// 地址化 IO(大端序)
service.WriteBool("I0.0", true);
int16_t cmd = service.ReadInt16("QW0");
printf("控制器输出字 QW0 = %d\n", cmd);
service.Stop();
service.Close();
return 0;
}