java - 解析 SWIG 接口(interface)文件的结构属性

标签 java c swig

这是我不久前问过的问题的延续。 Create a typemap for a function that returns through arguments

上一个问题中的接口(interface)文件如下:

%module test

%{
#include "header.h"
%}

%inline %{
  %immutable;
  struct FieldFetch {
    int status;
    int type;
    char *value;
  };
  %mutable;

  struct FieldFetch gaiaTextReaderFetchField(gaiaTextReaderPtr reader, int field_num) {
    struct FieldFetch result;
    result.status = gaiaTextReaderFetchField(reader, field_num, &result.type, &result.value);
    return result;
  }
%}

%ignore gaiaTextReaderFetchField;
%include "header.h"

我现在必须解析位于 structs.h 中的 gaiaTextReaderPtr 结构。 该结构位于以下代码的底部,尽管我也包含了其中的其他结构以提供完整的图片。

我用下划线划出了正在创建的 SWIG 不透明数据类型

/** Virtual Text driver: MAX number of fields */
#define VRTTXT_FIELDS_MAX   65535
/** Virtual Text driver: MAX block size (in bytes) */
#define VRTTXT_BLOCK_MAX 65535

/** Virtual Text driver: TEXT value */
#define VRTTXT_TEXT     1
/** Virtual Text driver: INTEGER value */
#define VRTTXT_INTEGER  2
/** Virtual Text driver: DOUBLE value */
#define VRTTXT_DOUBLE   3
/** Virtual Text driver: NULL value */
#define VRTTXT_NULL 4


/**
 Container for Virtual Text record (line)
 */
    struct vrttxt_line
    {
/* a struct representing a full LINE (aka Record) */
/** current offset (parsing) */
    off_t offset;
//__^________________________________________________________SWIGTYPE_p_off_t
/** line length (in bytes) */
    int len;
/** array of field offsets (where each field starts) */
    int field_offsets[VRTTXT_FIELDS_MAX];
//__^________________________________________________________SWIGTYPE_p_int
/** number of field into the record */
    int num_fields;
/** validity flag */
    int error;
    };

/**
 Container for Virtual Text record (line) offsets 
 */
    struct vrttxt_row
    {
/* a struct storing Row offsets */
/** Line Number */
    int line_no;
/** start offset */
    off_t offset;
//__^________________________________________________________SWIGTYPE_p_off_t
/** record (line) length (in bytes) */
    int len;
/** number of fields into this record */
    int num_fields;
    };

/**
 Container for Virtual Text block of records
 */
    struct vrttxt_row_block
    {
/*
/ for efficiency sake, individual Row offsets 
/ are grouped in reasonably sized blocks
*/
/** array of records [lines] */
    struct vrttxt_row rows[VRTTXT_BLOCK_MAX];
/** number of records into the array */
    int num_rows;
/** min Line Number */
    int min_line_no;
/** max Line Number */
    int max_line_no;
/** pointer to next item [linked list] */
    struct vrttxt_row_block *next;
    };

/** 
 Container for Virtual Text column (field) header
 */
    struct vrttxt_column_header
    {
/* a struct representing a Column (aka Field) header */
/** column name */
    char *name;
/** data type: one of GAIA_NULL_VALUE, GAIA_INT_VALUE, GAIA_DOUBLE_VALUE, GAIA_TEXT_VALUE */
    int type;
    };

/**
 Container for Virtual Text file handling
 */
    typedef struct vrttxt_reader
    {
/* the main TXT-Reader struct */
/** array of columns (fields) */
    struct vrttxt_column_header columns[VRTTXT_FIELDS_MAX];
/** FILE handle */
    FILE *text_file;
//__^________________________________________________________SWIGTYPE_p_FILE
/** handle to ICONV converter object */
    void *toUtf8;       /* the UTF-8 ICONV converter */
//__^________________________________________________________SWIGTYPE_p_void
/** field separator character */
    char field_separator;
/** text separator character (quote) */
    char text_separator;
/** decimal separator */
    char decimal_separator;
/** TRUE if the first line contains column names */
    int first_line_titles;
/** validity flag */
    int error;
/** pointer to first block of records [linked list] */
    struct vrttxt_row_block *first;
/** pointer to last block of records [linked list] */
    struct vrttxt_row_block *last;
/** array of pointers to individual records [lines] */
    struct vrttxt_row **rows;
//__^________________________________________________________SWIGTYPE_p_p_vrttxt_row
/** number of records */
    int num_rows;
/** current Line Number */
    int line_no;
/** max number of columns (fields) */
    int max_fields;
/** current buffer size */
    int current_buf_sz;
/** current buffer offset [parsing] */
    int current_buf_off;
/** I/O buffer */
    char *line_buffer;
/** current field buffer */
    char *field_buffer;
/** array of field offsets [current record] */
    int field_offsets[VRTTXT_FIELDS_MAX];
//__^________________________________________________________SWIGTYPE_p_int
/** array of field lengths [current record] */
    int field_lens[VRTTXT_FIELDS_MAX];
//__^________________________________________________________SWIGTYPE_p_int
/** max field [current record] */
    int max_current_field;
/** current record [line] ready for parsing */
    int current_line_ready;
    } gaiaTextReader;
/**
 Typedef for Virtual Text file handling structure

 \sa gaiaTextReader
 */
    typedef gaiaTextReader *gaiaTextReaderPtr;

任何解决问题的帮助将不胜感激! 问候汉克


第二部分

1: 一位开发人员对 void toUtf8 有这样的说法:

Hi Hank,

a "void *" pointer simply is a generic opaque memory pointer; it's basically an handle.

in the specific context "void *toUtf8" references the internal struct required by ICONV. the referenced object has to be created by a previous call to gaiaCreateUTF8Converter(), and is expected to be destroyed before or after by invoking gaiaFreeUTF8Converter(); each call to gaiaFreeUTF8Converter() requires this pointer to be passed as an argument.

From your Java/SWIG perspective it simply is a constant value to be passed back and forward exactly as it is. (any attempt to directly change, access or dereferencing this pointer could easily lead to some disaster == system crash)

bye Sandro

2:我还有一些其他结构,这些是 gg_structs.h 中的最后一个,使用以下结构时出现问题。

/** COORDs mem-array */
double *Coords;               /* X,Y [vertices] array */

目前我刚刚输入:

%apply double[] {double *};

这已经解决了,但是我不确定这是否正确。我应该单独瞄准阵列吗?实际上,我很确定这是不正确的,只需查看它创建的类,它就会显示:

  public void setCoords(double[] value) {
    gg_structsJNI.gaiaLinestring_Coords_set(swigCPtr, this, value);
  }

  public double[] getCoords() {
    return gg_structsJNI.gaiaLinestring_Coords_get(swigCPtr, this);
  }

这不应该有一个:int索引才能正常工作吗?对于双倍我这样做了:

%ignore Coords;
%include "gg_structs.h"

%extend gaiaLinestring {
  void setCoords(int index, double value) {
    $self->Coords[index] = value;
  }

  double getCoords(int index) {
    return $self->Coords + index;
  }
}

3:我有兴趣了解有关提供实现 AbstactSequentialList 的代理的更多信息。这就是所谓的动态代理吗?

最佳答案

其中一些类型很容易映射到 Java 中简单直观的东西:

  1. 对于off_t,您可以使用:

    %apply int { off_t };
    

    告诉 SWIG 将 off_t 视为 Java 中的 int。除非您期望 off_t 大于 int,否则这可能有效。对于一些常见的 typedef,SWIG 已经在库中提供了适当的映射,我有点惊讶 off_t 不是其中之一。

    (您还可以选择在接口(interface)文件中向 SWIG 显示 typedef,而不是使用 %apply)

  2. 对于“简单”数组(即不是结构的数组)执行的操作:

    %include <arrays_java.i> 
    

    足以生成直观的 Java 接口(interface),例如添加导致 int field_offsets[VRTTXT_FIELDS_MAX] 被包装为 public void setField_offsets(int[] value)以及相应的获取。在为 setter 生成的代码中,有一个测试来检查大小是否匹配 - 如果不匹配,则会在运行时抛出异常,因为 Java 中没有编译时数组大小的概念。

  3. 此答案讨论了 wrapping FILE* from Java 。在这种情况下,最简单的解决方案是使用如下内容:

    %ignore text_file
    %include "header.h"
    %extend gaiaTextReader {
      void setTextFile(const char *fn) {
        $self->text_file = fopen(fn, "r");
      }
    }
    

    它隐藏了text_file的自动设置/获取,而是公开了一个接受字符串并调用fopen的setter。

    您可以选择更复杂的实现,如链接答案中所示,显然仍然如此,或者您可以使用 %inline 来提供在 Java 中创建 SWIGTYPE_p_FILE 的替代方法。

  4. 对于结构数组,最简单的解决方案是再次使用 %ignore%extend,例如对于,这是:

    %ignore columns;    
    %include "header.h"
    
    %extend gaiaTextReader {
      struct vrttxt_column_header *getColumn(int i) {
        return $self->columns + i;
      }
    
      void setColumn(struct vrttxt_column_header *c, int i) {
        $self->columns[i] = *c;
      }
    }
    

    这比编写类型映射更简单(这将涉及大量 JNI 调用来将 Object 数组复制到结构数组中)。

    一个更优雅的解决方案可能是编写扩展AbstractList的东西(使用 Java code typemaps ,具体取决于您想要如何执行)在 Java 中以及通过您在 %extend

  5. 中公开的内容返回的代理
  6. 可以对 toUtf8 成员采取与 %extend 相同的方法:

    %ignore toUtf8;
    %include "header.h"
    
    %extend gaiaTextReader {
      void setToUtf8(const char *from) {
        $self->toUtf8 = iconv_open("tocode", from);
      }
    }
    

    (我不确定这个字段的用法是否正确,但无论如何原则都适用)。

  7. 您的链接列表已经可以从 Java 中“自然地”遍历,尽管再次提供一个实现 AbstractSequentialList 的代理是可能/明智的(?) .

  8. 对于实际上是一个枚举int,您仍然可以使用 proper Java enums来代表它:

    %include <enums.swg>
    %javaconst(1);
    
    enum Type;
    %typemap(jstype) int type "$typemap(jstype,enum Type)"
    %typemap(javain) int type "$typemap(javain,enum Type)"
    
    %include "header.h"
    
    enum Type { TEXT=VRTTXT_TEXT,
                INTEGER=VRTTXT_INTEGER,
                DOUBLE=VRTTXT_DOUBLE,
                NONE=VRTTXT_NULL };
    

    (这里的顺序很重要 - 伪造的 enum 需要发生在 %include 之后,但类型映射和前向声明需要发生在它之前)。

关于java - 解析 SWIG 接口(interface)文件的结构属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14132617/

相关文章:

java - 将我的 double 单元格变成 double 数组

c - 指针变量的地址是如何分配的?他们遵循任何模式吗?

java - 返回对成员变量的引用时的 SWIG-Java 内存管理

c - 未知的错误字符被添加到字符串中?

java - 我应该如何编写 .i 文件以用 Java 或 C# 包装回调

c++ - 在 Python 中使用自定义 Qt 子类

java - 从 JFormattedTextField 获取原始、未格式化、未屏蔽的文本

Java,如果我想从函数返回不同类型怎么办?

java - 如何使用 HttpResponse 检查响应正文是 SOAP 消息还是 XML 消息或 XSD 文档还是 WSDL 文档

c - 不安全的 C 函数和替换