Skip to content

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 调用顺序如下:

  1. 使用 op2_init 建立连接。
  2. 使用 op2_new_table 创建表,并通过 op2_add_column 定义字段。
  3. 使用 op2_new_request 创建请求对象。
  4. 使用 op2_set_table 把表绑定到请求。
  5. 使用 op2_set_optionop2_add_filterop2_set_indicesop2_set_indices_string 描述业务条件。
  6. 使用统一发送流程提交请求并获取响应。
  7. 读取结果并释放请求、响应、对象资源。
  8. 最后使用 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:设置请求选项,例如 ActionReqidSQLmodeinterval
  • 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)

    • 参数:
      • opop2_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:目标对象名,如 PointArchiveRealtime
    • 返回值: 表句柄;失败时返回 NULL
  • op2_add_column(table, name, type, length, mask, defval, expr)

    • 参数:
      • table:目标表句柄。
      • name:列名,如 IDGNTM
      • type:列类型(vtNullvtInt32vtString 等)。
      • 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:选项名,如 ActionReqidSQLmodeinterval
      • value:选项值字符串。
    • 返回值: 无返回值。
  • op2_add_filter(req, l, op, r, rel)

    • 参数:
      • req:请求对象。
      • l:左操作数字段名,如 TMGN
      • op:比较操作符,如 operGEoperLEoperLike
      • 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:索引字段名,常传 GNNULL
      • 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:点名数组。
      • onoff1 表示追加订阅,0 表示取消订阅。
    • 返回值: 0 表示成功,非 0 表示失败。

4. 按功能场景理解这些函数

4.1 查询场景

opio_selectopio_select_archive 展示了如何通过 op2_new_tableop2_add_columnop2_set_indicesop2_set_indices_stringop2_add_filterop2_set_option 组织查询请求,再由 opio_service 统一发送和读取结果。

4.2 写入场景

opio_update_realtimeopio_update_archiveopio_insertopio_updateopio_delete 分别演示了实时值写入、历史值写入、对象插入、对象更新和对象删除。它们共同体现了 op2_append_rowop2_new_rowop2_appendop2_bind_stringop2_bind_intop2_bind_int32op2_bind_double 的用法。

4.3 结果读取场景

opio_serviceopio_show_table 展示了结果表的读取模式,主要使用 op2_get_responseop2_next_contentop2_row_countop2_column_countop2_column_nameop2_set_rowidop2_column_typeop2_column_stringop2_column_intop2_column_double

4.4 异步订阅场景

opio_subscribeonRealtime 展示了如何通过 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 这类公共发送流程,减少重复的请求发送和资源释放逻辑。