当前位置: 首页 > 面试题库 >

解决SWIG接口文件的结构属性

公良奇
2023-03-14
问题内容

这是我前一段时间问过的问题的延续。为通过参数返回的函数创建类型图

在上一个问题中,接口文件如下:

%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: 一位开发人员曾这样说过toUtf8无效:

嗨,汉克,

“ void *”指针只是一个通用的不透明内存指针;它基本上是一个句柄。

在特定上下文中,“ void * toUtf8”引用了ICONV所需的内部结构。被引用的对象必须通过先前对gaiaCreateUTF8Converter()的调用来创建,并且期望在调用gaiaFreeUTF8Converter()之前或之后被销毁;每次对gaiaFreeUTF8Converter()的调用都需要将此指针作为参数传递。

从Java / SWIG角度来看,它只是一个常量,可以照原样传递。(任何直接更改,访问或取消引用此指针的尝试都很容易导致灾难==系统崩溃)

再见桑德罗

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视为intJava。除非您期望off_t大于一个int,否则这可能会起作用。对于某些常见的typedef,SWIG已经在库中提供了适当的映射,我有点惊讶off_t不是其中之一。

(您也可以选择在界面文件中显示SWIG typedef,而不是使用%apply

  1. 对于“简单”数组(即不是结构的事物的数组),其操作如下:
    %include <arrays_java.i>
    

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

  1. 这个答案讨论了Java的包装FILE*。在这种情况下,最简单的解决方案是使用类似以下内容的方法:
    %ignore text_file
    

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

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

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

  1. 至于结构的阵列,最简单的办法是使用%ignore%extend再次,例如对于columns这是:

    %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数组复制到结构数组)。

一个更优雅的解决方案可能是在Java中编写扩展的内容AbstractList(使用Java代码类型映射,具体取决于您要执行的操作),然后通过在Java中公开的内容来返回代理%extend

  1. 成员%extend可以采用相同的方法toUtf8

    %ignore toUtf8;
    

    %include “header.h”

    %extend gaiaTextReader {
    void setToUtf8(const char *from) {
    $self->toUtf8 = iconv_open(“tocode”, from);
    }
    }

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

  1. 您的链表可以从Java中“自然地”遍历,尽管有可能/明智的(?)提供实现的代理AbstractSequentialList

  2. 因为int确实如此,enum您仍然可以使用适当的Java枚举来表示它:

    %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,但是类型映射和前向声明需要发生在它之前)。



 类似资料:
  • 问题内容: 我正在使用SWIG为大量的C API生成我的JNI层,我想知道以下情况的最佳实践是什么。以下内容不仅适用于SWIG,而且适用于一般JNI。 当C函数返回指向Structures的指针时,应该大量使用SWIG接口文件(JNI逻辑)还是应该创建C包装函数以分段返回数据(即,包含各种数据元素的char数组)?当C函数返回void *时,是否应该修改C API以返回实际的数据类型,无论是原始类

  • 我想使用SWIG将暴露到Tcl层。但目前我不知道我可以暴露这个。我发现SWIG/Lib文件夹包含的接口文件。但在内容中我发现我不能直接使用它。它必须包含在“”之后。但在“”文件夹中没有像这样的东西但我们有类似的界面,我可以包含在Java中。

  • 我试图使用SWIG,以便在Android上使用Spotify API(libspotify):https://developer.spotify.com/technologies/libspotify/ 我在定义SWIG接口文件以成功调用以下本机C函数时遇到问题: 在C语言中被称为: 但在Java中,我需要这样称呼它: sp_会话是一个不透明的结构,仅在libspotify的API中定义。h文件格

  • 问题内容: 我在header.h内部定义了一个结构,如下所示: 当我用这种结构初始化一个对象时,我可以访问整数/双精度数,但不能访问数组。 如何访问读/写中的值? 问题答案: 最简单的方法是将数组包装在内,然后可以提供额外的方法来满足“可订阅”的要求。 我整理了一个小例子。假定您使用的是C ++,但是从中构造等效的C版本相当简单,它只需要重复一些即可。 首先,具有要包装的C ++头文件和用于包装固

  • 问题内容: 我正在使用SWIG制作C 库的Java包装器(关于Json(反)序列化),以便在Android上使用它。我用C 定义了一个抽象类,代表一个可以(反序列化)的对象: 现在,我正在尝试从此类生成Java接口。这是我的SWIG界面: 但是生成的Java代码(显然是,因为我无法找出如何告诉SWIG这是一个接口)是一个简单的类,带有两个方法和一个默认的构造函数/析构函数: 如何使用SWIG生成有

  • 本文向大家介绍C#结构实现接口,包括了C#结构实现接口的使用技巧和注意事项,需要的朋友参考一下 示例