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

这是我问过的一个问题的延续。 为通过参数返回的函数创建一个typemap

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

%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 opaque数据类型的行加下划线

 /** 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 *}; 

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

  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在Java中将off_t视为int 。 这可能有效,除非你期望off_t大于int。 对于一些常见的typedef,SWIG已经在库中提供了一个合适的映射,我有点惊讶,off_t不是其中之一。

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

  2. 对于“简单”数组(即不是结构的事物的数组)做:

     %include  

    足以生成直观的Java接口,例如添加导致int field_offsets[VRTTXT_FIELDS_MAX]被包装为public void setField_offsets(int[] value)和相应的get。 在生成器的生成代码内部有一个测试来检查大小匹配 – 如果它们没有,这将在运行时抛出exception,因为在Java中没有编译时数组大小的概念。

  3. 这个答案讨论了从Java包装FILE* 。 在这种情况下,最简单的解决方案是使用类似的东西:

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

    它隐藏了text_file的自动set / gets,而是公开了一个带字符串并调用fopen的setter。

    您可以选择更复杂的实现,就像在链接的答案中一样,或者您可以使用%inline来提供在Java中创建SWIGTYPE_p_FILE替代方法。

  4. 关于结构数组,最简单的解决方案是再次使用%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代码类型映射 ,具体取决于您希望如何实现)的内容,以及通过您在%extend公开的内容返回的代理

  5. 对于toUtf8成员,可以使用相同的%extend方法:

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

    (我不确定我是否正确使用这个领域,但无论如何都适用这个原则)。

  6. 您的链表可以从Java“自然地”遍历,尽管再次提供实现AbstractSequentialList的代理是可能/合理的(?)。

  7. 对于真正是enumint ,您仍然可以使用适当的Java枚举来表示它:

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