Appearance
openPlant CPP 接口说明
本文面向 openPlant 数据库的 C++ SDK 使用者,说明 API 的基本对象模型、请求调用流程、常见读写方式和异步订阅方式。详细接口说明请见Demo示例。
1. SDK 概览
openPlant CPP SDK 采用句柄式 API 设计,核心思路是先建立连接,再围绕连接句柄构造请求、发送请求并解析响应。常见的对象包括:
OpenPlant:数据库连接句柄op_request:请求对象op_response:响应对象op_table:请求或结果数据表op_row:表中的单行对象op_stream:底层传输流
SDK 主要覆盖以下能力:
- 连接与连接状态管理
- 当前值、快照值、历史值读写
- 数据库对象的插入、更新、删除
- SQL 执行
- 异步订阅和回调处理
2. 快速开始
一个典型的 SDK 调用顺序如下:
- 使用
op2_init建立连接。 - 使用
op2_new_table创建表,并通过op2_add_column定义字段。 - 使用
op2_new_request创建请求对象。 - 使用
op2_set_table把表绑定到请求。 - 使用
op2_set_option、op2_add_filter、op2_set_indices或op2_set_indices_string描述业务条件。 - 使用统一发送流程提交请求并获取响应。
- 读取结果并释放请求、响应、对象资源。
- 最后使用
op2_close关闭连接。
如果是异步订阅,则把第 6 步替换为 op2_open_async,并在回调中消费推送结果。
3. 常用的 SDK 函数
下面仅列出常用的相关函数,并按用途分组说明。
3.1 连接与时间
op2_init:建立 OpenPlant 连接,返回连接句柄。op2_close:关闭连接。op2_get_system_time:获取服务器当前系统时间。op2_decode_time:把时间值拆成年月日时分秒。op2_encode_time:把年月日时分秒编码成时间值。op2_sleep:异步订阅循环中等待指定毫秒数。
3.2 表、列、行与绑定
op2_new_table:创建请求或结果表。op2_add_column:为表增加字段定义。op2_append_row:向表中追加一行空记录。op2_new_row:创建单独的行对象。op2_append:把行对象追加到表中。op2_bind_string:给指定列绑定字符串值。op2_bind_int:给指定列绑定整型值。op2_bind_int32:给指定列绑定 32 位整型值。op2_bind_double:给指定列绑定双精度值。
3.3 请求组织
op2_new_request:创建请求对象。op2_set_table:把表绑定到请求。op2_set_option:设置请求选项,例如Action、Reqid、SQL、mode、interval。op2_add_filter:为请求添加过滤条件。op2_set_indices:按 ID 数组设置查询或订阅目标。op2_set_indices_string:按名称数组设置查询或订阅目标。
3.4 请求发送与响应读取
op2_get_table:从请求或响应中取表。op2_get_stream:获取底层传输流。op2_set_compress:设置传输压缩。op2_write_request:写出请求头。op2_write_content:写出表内容。op2_flush_content:刷新发送缓冲。op2_get_response:接收服务器响应。op2_next_content:继续读取响应内容。op2_get_errno:读取响应错误码。op2_get_error:读取响应错误信息。
3.5 结果遍历与释放
op2_row_count:获取结果表行数。op2_column_count:获取结果表列数。op2_column_name:获取列名。op2_set_rowid:设置当前行游标。op2_column_type:获取列类型。op2_column_string:读取字符串列值。op2_column_int:读取整型列值。op2_column_double:读取浮点列值。op2_free_request:释放请求对象。op2_free_response:释放响应对象。
3.6 异步订阅
op2_open_async:打开异步订阅通道并注册回调。op2_close_async:关闭异步订阅通道。
3.7 常用函数参数解释
以下参数解释覆盖常用函数。
返回值说明约定:
- 无返回值函数:统一标注为无返回值。
- 状态码函数:统一按
0表示成功、非0表示失败理解。
连接与时间
op2_init(option, host, port, timeout, user, password, buffer_path, buffer_size)- 参数:
option:连接选项位,常用0。host:服务端地址或主机名。port:服务端端口。timeout:网络超时秒数。user:用户名。password:密码。buffer_path:本地缓存目录,未启用可传NULL。buffer_size:缓存文件大小,未启用可传0。
- 返回值: 连接句柄;失败时返回
NULL。
- 参数:
op2_close(op)- 参数:
op:op2_init返回的连接句柄。
- 返回值: 无返回值。
- 参数:
op2_get_system_time(op, out)- 参数:
op:连接句柄。out:输出参数,返回服务器时间戳。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_decode_time(time, yy, mm, dd, hh, mi, ss)- 参数:
time:待拆分的时间戳。yy/mm/dd/hh/mi/ss:输出参数,分别返回年/月/日/时/分/秒。
- 返回值: 无返回值。
- 参数:
op2_encode_time(yy, mm, dd, hh, mi, ss)- 参数:
yy/mm/dd/hh/mi/ss:输入的年月日时分秒。
- 返回值: 时间戳值。
- 参数:
op2_sleep(ms)- 参数:
ms:睡眠毫秒数(常用于异步循环节流)。
- 返回值: 无返回值。
- 参数:
表、列、行
op2_new_table(name)- 参数:
name:目标对象名,如Point、Archive、Realtime。
- 返回值: 表句柄;失败时返回
NULL。
- 参数:
op2_add_column(table, name, type, length, mask, defval, expr)- 参数:
table:目标表句柄。name:列名,如ID、GN、TM。type:列类型(vtNull、vtInt32、vtString等)。length:长度(传0)。mask:掩码(传0)。defval:默认值表达(传NULL)。expr:计算表达式(传NULL)。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_append_row(table)- 参数:
table:目标表句柄,向表尾追加一行。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_new_row(table)- 参数:
table:所属表句柄,创建一个独立行对象。
- 返回值: 行句柄;失败时返回
NULL。
- 参数:
op2_append(table, row)- 参数:
table:目标表句柄。row:待追加的行对象。
- 返回值:
0表示成功,非0表示失败。
- 参数:
行绑定(写入列值)
op2_bind_string(row, col, value)- 参数:
row:行对象(本示例中常直接传table当前行)。col:列下标(从0开始)。value:字符串值。
- 返回值: 无返回值。
- 参数:
op2_bind_int(row, col, value)- 参数:
row:行对象或当前行。col:列下标。value:整型值(int64)。
- 返回值: 无返回值。
- 参数:
op2_bind_int32(row, col, value, mask=-1)- 参数:
row:行对象或当前行。col:列下标。value:32 位整型值。mask:可选掩码参数,默认-1。
- 返回值: 无返回值。
- 参数:
op2_bind_double(row, col, value)- 参数:
row:行对象或当前行。col:列下标。value:双精度浮点值。
- 返回值: 无返回值。
- 参数:
请求组织
op2_new_request()- 参数: 无参数。
- 返回值: 请求句柄;失败时返回
NULL。
op2_set_table(r, t)- 参数:
r:请求或响应对象。t:要绑定的表对象。
- 返回值: 无返回值。
- 参数:
op2_set_option(r, key, value)- 参数:
r:请求对象。key:选项名,如Action、Reqid、SQL、mode、interval。value:选项值字符串。
- 返回值: 无返回值。
- 参数:
op2_add_filter(req, l, op, r, rel)- 参数:
req:请求对象。l:左操作数字段名,如TM、GN。op:比较操作符,如operGE、operLE、operLike。r:右操作数(字符串形式的值或表达式)。rel:与下一个条件关系,如relationAnd。
- 返回值: 无返回值。
- 参数:
op2_set_indices(r, name, count, keys)- 参数:
r:请求对象。name:索引字段名,传NULL表示默认主索引。count:键数量。keys:整型索引数组(使用 ID 列表)。
- 返回值: 无返回值。
- 参数:
op2_set_indices_string(r, name, count, keys)- 参数:
r:请求对象。name:索引字段名,常传GN或NULL。count:键数量。keys:字符串索引数组(使用点名列表)。
- 返回值: 无返回值。
- 参数:
请求发送与响应接收
op2_get_table(r)- 参数:
r:请求或响应对象。
- 返回值: 表句柄;无表时返回
NULL。
- 参数:
op2_get_stream(openplant)- 参数:
openplant:连接句柄。
- 返回值: 流句柄;失败时返回
NULL。
- 参数:
op2_set_compress(opio, zip)- 参数:
opio:流对象。zip:压缩模式(0:关闭压缩(默认),1:lz4 frame模式,2:lz4 block模式)。
- 返回值: 无返回值。
- 参数:
op2_write_request(opio, r)- 参数:
opio:流对象。r:请求对象。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_write_content(opio, t)- 参数:
opio:流对象。t:请求内容表。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_flush_content(opio)- 参数:
opio:流对象,立即刷新发送缓冲。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_get_response(opio, r)- 参数:
opio:流对象。r:输出参数,返回响应对象指针。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_next_content(opio, result, clear, eof)- 参数:
opio:流对象。result:目标结果表。clear:是否先清空结果表(示例用false)。eof:输出参数,是否已读到末尾。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_get_errno(r)- 参数:
r:响应对象。
- 返回值:
0表示无错误,非0为错误码。
- 参数:
op2_get_error(r)- 参数:
r:请求或响应对象。
- 返回值: 错误描述字符串指针。
- 参数:
结果读取
op2_row_count(table)- 参数:
table:结果表对象。
- 返回值: 结果行数。
- 参数:
op2_column_count(table)- 参数:
table:结果表对象。
- 返回值:
0表示无列或失败,正数表示列数。
- 参数:
op2_column_name(rowOrTable, col)- 参数:
rowOrTable:行/表对象。col:列下标。
- 返回值: 列名字符串(失败时返回
NULL)。
- 参数:
op2_set_rowid(table, rowid)- 参数:
table:结果表对象。rowid:当前行游标。
- 返回值:
0表示成功,非0表示失败。
- 参数:
op2_column_type(rowOrTable, col)- 参数:
rowOrTable:行/表对象。col:列下标。
- 返回值: 类型枚举值(无效列时返回无效类型值)。
- 参数:
op2_column_string(rowOrTable, col)- 参数:
rowOrTable:行/表对象。col:列下标。
- 返回值: 字符串值指针(无值时返回
NULL)。
- 参数:
op2_column_int(rowOrTable, col)- 参数:
rowOrTable:行/表对象。col:列下标。
- 返回值: 整型列值。
- 参数:
op2_column_double(rowOrTable, col)- 参数:
rowOrTable:行/表对象。col:列下标。
- 返回值: 浮点列值。
- 参数:
资源释放
op2_free_request(r)- 参数:
r:请求对象。
- 返回值: 无返回值。
- 参数:
op2_free_response(r)- 参数:
r:响应对象。
- 返回值: 无返回值。
- 参数:
异步订阅
op2_open_async(op, r, cb, owner, error)- 参数:
op:连接句柄。r:订阅请求对象。cb:回调函数,签名为void (*)(void*, op_response)。owner:回调透传的用户上下文。error:输出参数,返回打开订阅时的错误码。
- 返回值: 异步句柄;失败时返回
NULL。
- 参数:
op2_close_async(ah)- 参数:
ah:异步订阅句柄(op2_open_async返回值)。
- 返回值: 无返回值。
- 参数:
op2_async_subscribe_tags(ah, count, tags, onoff)- 参数:
ah:异步订阅句柄。count:点名数量。tags:点名数组。onoff:1表示追加订阅,0表示取消订阅。
- 返回值:
0表示成功,非0表示失败。
- 参数:
4. 按功能场景理解这些函数
4.1 查询场景
opio_select 和 opio_select_archive 展示了如何通过 op2_new_table、op2_add_column、op2_set_indices、op2_set_indices_string、op2_add_filter 和 op2_set_option 组织查询请求,再由 opio_service 统一发送和读取结果。
4.2 写入场景
opio_update_realtime、opio_update_archive、opio_insert、opio_update 和 opio_delete 分别演示了实时值写入、历史值写入、对象插入、对象更新和对象删除。它们共同体现了 op2_append_row、op2_new_row、op2_append、op2_bind_string、op2_bind_int、op2_bind_int32 和 op2_bind_double 的用法。
4.3 结果读取场景
opio_service 和 opio_show_table 展示了结果表的读取模式,主要使用 op2_get_response、op2_next_content、op2_row_count、op2_column_count、op2_column_name、op2_set_rowid、op2_column_type、op2_column_string、op2_column_int、op2_column_double。
4.4 异步订阅场景
opio_subscribe 和 onRealtime 展示了如何通过 op2_open_async 订阅实时数据,并在回调中读取响应表内容,最后用 op2_close_async 结束订阅。
5. 示例代码
下面给出三个最常见场景的最小可用代码片段。示例复用源文件中的 opio_service 发送流程。
5.1 Select 示例
cpp
int sample_select(OpenPlant op)
{
op_table table = op2_new_table("Point");
op2_add_column(table, "ID", vtNull, 0, 0, NULL, NULL);
op2_add_column(table, "ND", vtNull, 0, 0, NULL, NULL);
op2_add_column(table, "PN", vtNull, 0, 0, NULL, NULL);
op2_add_column(table, "ED", vtNull, 0, 0, NULL, NULL);
op_request request = op2_new_request();
op2_set_table(request, table);
op2_set_option(request, "Reqid", "1");
op2_set_option(request, "Action", "Select");
const char *tags[] = { "W3.SYS.SESSION" };
op2_set_indices_string(request, NULL, 1, tags);
return opio_service(op, request, b, true);
}5.2 Update 示例
cpp
int sample_update(OpenPlant op)
{
op_table table = op2_new_table("Point");
op2_add_column(table, "ND", vtInt32, 0, 0, NULL, NULL);
op2_add_column(table, "PN", vtString, 0, 0, NULL, NULL);
op2_add_column(table, "ED", vtString, 0, 0, NULL, NULL);
op2_append_row(table);
op2_bind_int(table, 0, 14);
op2_bind_string(table, 1, "AX");
op2_bind_string(table, 2, "This is a test");
op_request request = op2_new_request();
op2_set_table(request, table);
op2_set_option(request, "Reqid", "1");
op2_set_option(request, "Action", "Update");
return opio_service(op, request, b, true);
}5.3 Exec SQL 示例
cpp
int sample_exec_sql(OpenPlant op)
{
op_request request = op2_new_request();
op2_set_option(request, "Reqid", "1");
op2_set_option(request, "Action", "ExecSQL");
op2_set_option(request, "SQL", "select count(*) from Database");
return opio_service(op, request, b, true);
}6. 使用建议
- 这份文档只覆盖源文件中实际用到的相关函数,便于与源代码一一对应。
- 如果需要扩展到更多 SDK 接口,请以 include/opapi2.h 和 include/op_service.h 为准,单独补充新章节。
- 代码实践时建议优先复用
opio_service这类公共发送流程,减少重复的请求发送和资源释放逻辑。
帮助中心