17.2 控制参数

HALCON/C 支持以下数据类型作为 HALCON 算子的控制参数类型:

17.2.1 字符串编码

无论 HALCON 库的编码方式如何(set_system('filename_encoding', ...)),HALCON/C 接口都希望传递给 HALCON 算子和 Htuple 实例的原始字符指针字符串采用 UTF-8 编码。可以通过调用 SetHcInterfaceStringEncodingIsUtf8(false) 将 HALCON/C 接口的编码(接口编码)更改为本地 8 位编码。 ! 请注意,使用 HDevEngine 时不得更改编码。可以通过 IsHcInterfaceStringEncodingUtf8() 请求当前的接口编码。不建议来回切换接口编码。只应在程序开始时(第一个 HALCON 算子或赋值之前)调整一次设置,因为 Htuple 结构无法存储所含字符串的编码,也就是说,所有写入和读取访问都必须设置相同的编码。此外,接口编码是全局设置的,因此不适合多线程程序: 在一个线程中更改设置会对其他线程产生影响。还要注意的是,UTF-8 编码字符串可能比本地 8 位编码字符串占用更多内存空间。在为 HALCON 算子返回的字符串提供缓冲区时,必须考虑到这一点。如果不能确定返回字符串的最大长度,建议优先使用元组模式而不是简单模式的算子调用。

如果需要在不改变接口编码的情况下转换字符串编码,可使用以下函数将 wchar_t* 字符串和 char* 字符串转换为元组或从元组转换为字符串:


UTF-8 版本 本地 8 位版本 wchar_t* 版本(仅限 Windows)

create_tuple_s_from_utf8 create_tuple_s_from_local8bit create_tuple_s_from_wcs

reuse_tuple_s_from_utf8 reuse_tuple_s_from_local8bit reuse_tuple_s_from_wcs

init_s_from_utf8 init_s_from_local8bit init_s_from_wcs

set_s_from_utf8 set_s_from_local8bit set_s_from_wcs

get_s_to_utf8 get_s_to_local8bit get_s_to_wcs

表 17.1: 编码辅助函数

当转换为不同的编码时,字符串可能需要更大的缓冲区。要检查是否需要为字符串分配更多内存,可以使用上表中提到的 get_s_too_* 函数(另见 图 17.7)。这些函数将字符串转码为相应的编码,并将其写入用户提供的缓冲区。如果返回的字符串大小大于或等于所提供的缓冲区,则说明所传递的缓冲区太小。

17.2.2 控制参数元组

在 C 中使用控制参数元组不如使用图像对象元组那么优雅。为了规避 C 中缺失的通用列表,有必要在 HALCON/C 中引入两种不同的工作模式:简单模式元组模式。如果至少有一个控制参数需要元组,那么算子调用就必须使用元组模式。在元组模式下,算子的所有控制参数都必须以 Htuple 类型传递。两种模式不能混用。如果事先不知道算子计算值的数量或类型,也必须使用元组模式。

基本上,有三种方法可以确定给定算子的默认控制参数类型:

有时手册中提到的可能类型不止一种。如果参数只允许使用整数和浮点数,则必须将数值作为 double 类型的参数传递。对于所有其他类型组合,必须使用元组模式。

在元组模式下调用的 HALCON 算子与简单模式下调用的 HALCON 算子的区别在于前面的 T_。也就是说,下面是在简单模式下对 HALCON 算子 select_shape 的调用(如 HALCON 参考手册所述 )

    select_shape

然而

    T_select_shape

是在元组模式下对同一算子的调用。

17.2.3 简单模式

在所谓的简单模式下,算子调用的所有控制参数都是数据类型如下的变量(或常量

Hlongdouble 输入控制参数像往常一样通过值传递,而相应的输出控制参数则使用 & 操作符通过引用传递。字符串参数在这两种情况下都是指向 char 的指针。请注意,输出控制参数(尤其是字符串)的内存必须由调用者提供!我们建议为未知长度的字符串参数分配至少 1024 个字符的内存。对于不再感兴趣的输出参数值,可以设置为 NULL

图 17.1图 16.1 中的 C 程序提供了在简单模式下调用 HALCON 算子的示例。

参数类似句柄的算子必须始终在元组模式下调用,如下节所述。这些算子的简单模式只有在传统句柄模式下才可用(参见 set_system)。

17.2.4 元组模式

我们已经提到,HALCON 算子的控制参数元组需要特殊处理。本章将详细介绍如何构造和使用这些元组。HALCON 参考手册描述了大量不对单个控制值而是对数值元组进行操作的算子。使用这些算子可以轻松编写非常紧凑和高效的程序,因为通常可以将多个类似的算子调用合并为一次调用。

遗憾的是,C 没有提供通用的元组或列表构造函数。相比之下,HALCON 允许将混合类型的元组作为控制参数值(例如,整数与浮点数混合)。

因此,除了非常直观的简单模式外,HALCON/C 中还有另一种模式:元组模式。这种模式的使用比较复杂。如果 HALCON 算子的至少一个控制参数以元组形式传递,则所有控制参数都必须使用元组模式(两种模式不能混合使用)。此外,如果事先不知道计算值的数量类型,也必须使用元组模式。

在语法上,元组模式与简单模式的区别在于算子名称前的 T_。例如,在元组模式下调用 disp_circle 的方法是

    T_disp_circle(...)

为了简化元组模式的使用,HALCON/C 为控制参数元组提供了抽象数据类型 HtupleHtuple 类型的对象可以使用以下类型的数组来构造

此外,还支持 MIXED_PAR 数组类型,该类型可以任意组合三种本地值类型来保存数组。这四种数组类型的使用是透明的。

控制参数元组的创建、删除和操作只能使用相应的 HALCON/C 函数(图 17.2图 17.3图 17.4图 17.5 概述)。

参数传递规则也适用于元组模式: 输入控制参数(Htuple 类型)像往常一样通过值传递,输出控制参数通过引用传递,使用"&"操作符。对于没有其他意义的输出参数,可以传递 NULL

下文将介绍在元组模式下调用 HALCON 算子时最重要的五个步骤:

"元组模式示例" 一节 包含一个示例。

最后,"通用调用机制" 一节 介绍了可用于解释器或图形用户界面的通用调用机制。

17.2.4.1 分配内存

首先,必须分别使用 create_tuplecreate_tuple_type 为所有输入控制参数元组分配内存(见 图 17.2 )。输出控制参数元组的内存由 HALCON/C 分配(无需调用 create_tuple)。通过 create_tuple_i 等命令,可以创建长度为 1 的元组,并在一个步骤中设置其值(见 图 17.3 )。使用 reuse_tuple_i 等命令,可以重复使用现有的元组,即销毁并重新分配,然后设置一个值(见 图 17.4 )。

  void create_tuple(tuple,length)     or     macro CT(tuple,length)
       Htuple    *tuple;
       Hlong      length;
       /* creates a MIXED_PAR tuple that can hold 'length' entries h  */

  void create_tuple_type(tuple,length,type)
       Htuple    *tuple;
       Hlong      length;
       Hlong      type;
       /* creates a tuple of 'type' that can hold 'length' entries.
        * 'type' can hold either LONG_PAR, DOUBLE_PAR, STRING_PAR,
        * HANDLE_PAR, or MIXED_PAR.                                   */

  void destroy_tuple(tuple)           or     macro DT(tuple)
       Htuple    tuple;
       /* deletes a tuple (if the tuple contains string entries,      */
       /* the memory allocated by the strings is freed, too)          */

  Hlong length_tuple(tuple)            or     macro LT(tuple)
       Htuple    tuple;
       /* returns the length of a tuple (number of entries)           */

  void copy_tuple(input,output)      or     macro CPT(input,output)
       Htuple    input;
       Htuple    *output;
       /* creates a tuple and copies the entries of the input tuple   */

  void resize_tuple(htuple,new_length) or   macro RT(htuple,new_length)
       Htuple    *htuple;
       Hlong      new_length;
       /* creates a tuple with the new size and copies the previous   */
       /* entries                                                     */

图 17.2:HALCON/C Htuple 函数 (1/6)。

  void create_tuple_i(tuple,value)
       Htuple    *tuple;
       Hlong      val;
       /* creates a tuple with specified integer value                */

  void create_tuple_d(tuple,value)
       Htuple    *tuple;
       double    val;
       /* creates a tuple with specified double value                 */

  void create_tuple_h(tuple,value)
       Htuple    *tuple;
       Hphandle  val;
       /* creates a tuple with specified handle value                 */

  void create_tuple_s(tuple,value)
       Htuple    *tuple;
       char      *val;
       /* creates a tuple with specified string value                 */

  void create_tuple_s_from_local8bit(tuple,value)
       Htuple    *tuple;
       char      *val;
       /* creates a tuple with specified string value converted       */
       /* from local-8-bit encoding                                   */

  void create_tuple_s_from_utf8(tuple,value)
       Htuple    *tuple;
       char      *val;
       /* creates a tuple with specified string value converted       */
       /* from UTF-8 encoding                                         */

  void create_tuple_s_from_wcs(tuple,value)
       Htuple    *tuple;
       wchar_t   *val;
       /* creates a tuple with specified string value converted       */
       /* from wide-character encoding                                */

图 17.3:HALCON/C Htuple 函数 (2/6)。

  void reuse_tuple_i(tuple,val)
       Htuple    *tuple;
       Hlong      val;
       /* reuses a tuple with specified integer value                 */

  void reuse_tuple_d(tuple,val)
       Htuple    *tuple;
       double    val;
       /* reuses a tuple with specified double value                  */

  void reuse_tuple_h(tuple,val)
       Htuple    *tuple;
       Hphandle  val;
       /* reuses a tuple with specified handle value                  */

  void reuse_tuple_s(tuple,val)
       Htuple    *tuple;
       char      *val;
       /* reuses a tuple with specified string value                  */

  void reuse_tuple_s_from_local8bit(tuple,val)
       Htuple    *tuple;
       char      *val;
       /* reuses a tuple with specified string value converted        */
       /* from local-8-bit encoding                                   */

  void reuse_tuple_s_from_utf8(tuple,val)
       Htuple    *tuple;
       char      *val;
       /* reuses a tuple with specified string value converted        */
       /* from UTF-8 encoding                                         */

  void reuse_tuple_s_from_wcs(tuple,val)
       Htuple    *tuple;
       wchar_t   *val;
       /* reuses a tuple with specified string value converted        */
       /* from wide-character encoding                                */

图 17.4:HALCON/C Htuple 函数 (3/6)。

17.2.4.2 创建输入参数

您可以使用适当的函数 set_*. set_s 设置元组元素,它们会将字符串插入元组,自己分配所需的内存,然后复制字符串(见 图 17.5 )。

17.2.4.3 调用算子

然后,实际调用 HALCON 算子。算子名称前面有一个 T_(如前所述),表示元组模式。

17.2.4.4 处理输出参数

使用程序 length_tupleget_type(见 图 17.2 )和 get_*(见 图 17.6图 17.7 )对输出参数元组进行进一步处理。在处理字符串时(使用 get_s),请注意在使用 destroy_tuple 删除元组时,分配的内存会被自动释放。如果在删除元组后仍要处理字符串,则必须先复制整个字符串。还要注意的是,删除最后一个元组时可能会释放输出句柄。如果需要继续使用句柄,则应将其保留在一个元组中。

  void set_i(tuple,val,index)                           or     macro SI(tuple,val,index)
       Htuple     tuple;
       Hlong      val;
       Hlong      index;
       /* inserts an integer with value 'val' into a tuple at         */
       /* position 'index' ('index' in [0,length_tuple(tuple) - 1])   */

  void set_d(tuple,val,index)                           or     macro SD(tuple,val,index)
       Htuple     tuple;
       double     val;
       Hlong      index;
       /* inserts a double with value 'val' into a tuple at           */
       /* position 'index' ('index' in [0,length_tuple(tuple) - 1])   */

  void set_h(tuple,val,index)                           or     macro SH(tuple,val,index)
       Htuple     tuple;
       Hphandle   val;
       Hlong      index;
       /* inserts a handle with value 'val' into a tuple at           */
       /* position 'index' ('index' in [0,length_tuple(tuple) - 1])   */

  void set_s(tuple,val,index)                           or     macro SS(tuple,val,index)
       Htuple     tuple;
       char       *val;
       Hlong      index;
       /* inserts a copy of string 'val' into a tuple at position     */
       /* 'index' ('index' in [0,length_tuple(tuple) - 1]);           */
       /* memory necessary for the string is allocated by set_s       */

  void set_s_from_local8bit(tuple,val,index)            or     macro SS_LOC(tuple,val,index)
       Htuple     tuple;
       char       *val;
       Hlong      index;
       /* inserts a copy of string 'val', converted from              */
       /* local-8-bit encoding, into a tuple at position 'index'      */
       /* ('index' in [0,length_tuple(tuple) - 1]).                   */

  void set_s_from_utf8(tuple,val,index)                 or     macro SS_U(tuple,val,index)
       Htuple     tuple;
       char       *val;
       Hlong      index;
       /* inserts a copy of string 'val', converted from UTF-8        */
       /* encoding, into a tuple at position 'index' ('index' in      */
       /* [0,length_tuple(tuple) - 1]).                               */

  void set_s_from_wcs(tuple,val,index)                  or     macro SS_W(tuple,val,index)
       Htuple     tuple;
       wchar_t    *val;
       Hlong      index;
       /* inserts a copy of string 'val', converted from              */
       /* wide-character encoding, into a tuple at position           */
       /* 'index' ('index' in [0,length_tuple(tuple) - 1]).           */

图 17.5:HALCON/C Htuple 函数 (4/6)。

  int get_type(tuple,index)                             or     macro GT(tuple,index)
       Htuple     tuple;
       Hlong      index;
       /* returns type of value at position 'index' in the tuple.     */
       /* Possible values: LONG_PAR, DOUBLE_PAR or STRING_PAR         */

  Hlong get_i(tuple,index)                              or     macro GI(tuple,index)
       Htuple     tuple;
       Hlong      index;
       /* returns the integer at position 'index' in the tuple        */
       /* (a type error results in a run time error)                  */

  double get_d(tuple,index)                             or     macro GD(tuple,index)
          Htuple     tuple;
          Hlong      index;
       /* returns the floating point number at position 'index' in    */
       /* the tuple. (a type error results in a run time error)       */

  Hphandle get_h(tuple,index)                           or     macro GH(tuple,index)
          Htuple     tuple;
          Hlong      index;
       /* returns the handle at position 'index' in the               */
       /* tuple. (a type error results in a run time error)           */

  char *get_s(tuple,index)                              or     macro GS(tuple,index)
        Htuple     tuple;
        Hlong      index;
       /* returns the pointer(!) to the string at position 'index'    */
       /* in the tuple. (a type error results in a run time error)    */
       /* Attention: indices must be in [0,length_tuple(tuple) - 1]   */

图 17.6:HALCON/C Htuple 函数 (5/6)。

  Hlong get_s_to_local8bit(buffer,size,tuple,index)   or     macro GS_LOC(tuple,index)
        char*      buffer;
        Hlong      size;
        Htuple     tuple;
        Hlong      index;
       /* Copies the (local-8-bit encoded) string at position         */
       /* 'index' into 'buffer'. 'size' determines the size of the    */
       /* buffer. The return value determines the size of the         */
       /* string, that would be written. If the returned length of    */
       /* the string is greater or equal to the provided              */
       /* buffer, the buffer was too small.                           */
       /* Attention: indices must be in [0,length_tuple(tuple) - 1]   */

  Hlong get_s_to_utf8(buffer,size,tuple,index)        or     macro GS_U(tuple,index)
        char*      buffer;
        Hlong      size;
        Htuple     tuple;
        Hlong      index;
       /* Copies the (UTF-8) string at position                       */
       /* 'index' into 'buffer'. 'size' determines the size of the    */
       /* buffer. The return value determines the size of the         */
       /* string, that would be written. If the returned length of    */
       /* the string is greater or equal to the provided              */
       /* buffer, the buffer was too small.                           */
       /* Attention: indices must be in [0,length_tuple(tuple) - 1]   */

  Hlong *get_s_to_wcs(buffer,size,tuple,index)        or     macro GS_W(tuple,index)
        wchar_t*   buffer;
        Hlong      size;
        Htuple     tuple;
        Hlong      index;
       /* Copies the (wide-character) string at position              */
       /* 'index' into 'buffer'. 'size' determines the size of the    */
       /* buffer. The return value determines the size of the         */
       /* string, that would be written. If the returned length of    */
       /* the string is greater or equal to the provided              */
       /* buffer, the buffer was too small.                           */
       /* Attention: indices must be in [0,length_tuple(tuple) - 1]   */

图 17.7:HALCON/C Htuple 函数 (6/6)。

17.2.4.5 释放内存

最后,必须再次释放所有元组(输入和输出)分配的内存。这可以通过 destroy_tuple 来完成。如果还需要元组变量的值,记得先复制它们。现在,整个系列可以重新开始--使用不同或相同的元组变量。

17.2.4.6 元组模式示例

元组模式的示例见 图 17.8 或文件 example3.c: 目的是获取有关当前 HALCON 系统状态的信息。算子 get_system('?',Values)(此处使用 HDevelop 语法)返回所有系统标志及其当前值。由于在我们的例子中,输出参数的数量和类型都无法预先知道,因此我们必须在 HALCON/C 中使用元组模式来实际调用算子。程序的其余部分不言自明。

#include "HalconC.h"

main ()
{
  Htuple In, SysFlags, Info;
  Hlong  i, num;

  printf("System information:\n");
  /* prepare query */
  create_tuple(&In, 1);
  /* "?" = list of all informations */
  set_s(In, "?", 0);
  T_get_system(In, &SysFlags);
  destroy_tuple(In);
  num = length_tuple(SysFlags);
  for (i = 0; i < num; i++)
  {
    create_tuple(&In, 1);
    set_s(In, get_s(SysFlags, i), 0);
    printf("%s ", get_s(SysFlags, i));
    T_get_system(In, &Info);
    destroy_tuple(In);
    if (length_tuple(Info) > 0)
    {
      switch (get_type(Info, 0))
      {
      case INT_PAR:
        printf("(Hlong):  %" LONG_FORMAT "d\n", get_i(Info, 0));
        break;
      case DOUBLE_PAR:
        printf("(double):  %f\n", get_d(Info, 0));
        break;
      case STRING_PAR:
        printf("(string):  %s\n", get_s(Info, 0));
        break;
      case HANDLE_PAR:
        printf("(handle):  %" LONG_FORMAT "d\n", (Hlong)get_h(Info, 0));
        break;
      }
    }
    else
    {
      printf("(--):  no data\n");
    }
    destroy_tuple(Info);
  }
}

图 17.8:元组模式示例程序: 打印当前 HALCON 系统状态。

17.2.4.7 通用调用机制

在元组模式下,HALCON 算子还有另一种通用调用机制。这种机制适用于解释器或图形用户界面:

    T_call_halcon_by_id(id, ...)

以元组模式调用 HALCON 算子 id,传递输入参数并获取输出参数(完整签名见 图 17.9)。算子 id 可以通过 get_operator_id 调用。

  /* generic HALCON operator call style:
   * - the operator is called by an id that is returned by get_operator_id;
   *    attention: this id may differ for different HALCON versions
   * - the tuple arrays are passed directly to the call -> this method is
   *   thread-safe
   *-----------------------------------------------------------------------*/
  int    get_operator_id(const char* name);

  Herror T_call_halcon_by_id(int id,
                             const Hobject in_objs[],
                             Hobject out_objs[],
                             const Htuple in_ctrls[],
                             Htuple out_ctrls[]);

图 17.9:HALCON/C 元组模式的通用调用机制。