this is a continuation of question I asked a while back. Create a typemap for a function that returns through arguments
In the previous question the interface file i
A few of these types are quite easy to map onto something simple and intuitive in Java:
For off_t
you can use:
%apply int { off_t };
to tell SWIG to treat off_t
as int
in Java. That probably works unless you're expecting off_t
to be bigger than an int. For some common typedefs SWIG supplies an appropriate mapping in the library already, I'm slightly surprised off_t isn't one of them.
(You could also choose to show SWIG a typedef in your interface file instead of using %apply
)
For the "simple" arrays (i.e. arrays of things which aren't a struct) doing:
%include <arrays_java.i>
is sufficient to get an intuitive Java interface generated, for example adding that causes int field_offsets[VRTTXT_FIELDS_MAX]
to be wrapped as public void setField_offsets(int[] value)
and a corresponding get. Inside the generated code for the setter there is a test to check the sizes match - this will throw an exception at runtime if they don't, since there's no concept of compile time array size in Java.
This answer discussed wrapping FILE* from Java. In this instance the simplest solution would be to use something like:
%ignore text_file
%include "header.h"
%extend gaiaTextReader {
void setTextFile(const char *fn) {
$self->text_file = fopen(fn, "r");
}
}
which hides the automatic set/gets for text_file
and instead exposes a setter that takes a string and calls fopen
.
You could choose the more complex implementation as in the linked answer still obviously, or you could use %inline
instead to provide alternative ways of creating a SWIGTYPE_p_FILE
in Java.
With regards to the arrays of structs the simplest solution would be to use %ignore
and %extend
again, e.g. for columns
this is:
%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;
}
}
This is simpler than writing a typemap (which would involve a lot of JNI calls to do the copy from an Object
array into the array of structs).
A more elegant solution might be to write something that extends AbstractList (using Java code typemaps, depending on how exactly you wanted to do it) in Java and proxies that back via something you've exposed in %extend
The same approach to %extend
can be taken with the toUtf8
member:
%ignore toUtf8;
%include "header.h"
%extend gaiaTextReader {
void setToUtf8(const char *from) {
$self->toUtf8 = iconv_open("tocode", from);
}
}
(I'm not sure I've got the usage of this field quite right, but the principle applies regardless).
Your linked list can be traversed "naturally" from Java already although again it would be possible/sensible(?) to provide a proxy that implements AbstractSequentialList.
For the int
that's really an enum
you could still use proper Java enums to represent it:
%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 };
(The order here is important - the faked enum
needs to happen after the %include
, but the typemaps and the forward declaration need to happen before it).