这是我问过的一个问题的延续。 Create a typemap for a function that returns through arguments
在上一个问题中,接口文件如下:
%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:其中一位开发人员对此表示无效:utf8:
嗨汉克,
“void *”指针只是一个通用的不透明内存指针;它的 基本上是一个句柄。
在特定上下文中“void * toUtf8”引用内部结构 ICONV要求。引用的对象必须由a创建 以前调用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的代理的更多信息。这是什么称为动态代理?
答案 0 :(得分:1)
这些类型中的一些很容易在Java中映射到简单直观的东西:
对于off_t
,您可以使用:
%apply int { off_t };
告诉SWIG在Java中将off_t
视为int
。除非你期望off_t
大于int,否则这可能有效。对于一些常见的typedef,SWIG已经在库中提供了一个合适的映射,我有点惊讶off_t不是其中之一。
(您也可以选择在界面文件中显示SWIG的typedef,而不是使用%apply
)
对于“简单”数组(即不是结构的事物数组)执行:
%include <arrays_java.i>
足以生成直观的Java界面,例如添加导致int field_offsets[VRTTXT_FIELDS_MAX]
包装为public void setField_offsets(int[] value)
和相应的get。在生成器的生成代码中,有一个测试来检查大小匹配 - 如果它们没有,这将在运行时抛出异常,因为在Java中没有编译时数组大小的概念。
这个答案讨论了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
的替代方法。
关于结构数组,最简单的解决方案是再次使用%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 code typemaps(取决于您想要如何完成)的内容)以及通过您在%extend
%extend
成员可采用与toUtf8
相同的方法:
%ignore toUtf8;
%include "header.h"
%extend gaiaTextReader {
void setToUtf8(const char *from) {
$self->toUtf8 = iconv_open("tocode", from);
}
}
(我不确定我是否正确使用这个字段,但无论如何都适用该原则。)
您的链接列表可以“自然地”从Java中遍历,尽管再次提供实现AbstractSequentialList
的代理是可能的/合理的(?)。
对于真正属int
的{{1}},您仍然可以使用proper Java enums来代表它:
enum
(这里的顺序很重要 - 伪造的%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
之后发生,但是字体图和前向声明需要在它之前发生。)