Resolving struct properties for SWIG interface file

后端 未结 1 697
孤独总比滥情好
孤独总比滥情好 2021-01-16 17:01

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

相关标签:
1条回答
  • A few of these types are quite easy to map onto something simple and intuitive in Java:

    1. 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)

    2. 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.

    3. 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.

    4. 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

    5. 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).

    6. Your linked list can be traversed "naturally" from Java already although again it would be possible/sensible(?) to provide a proxy that implements AbstractSequentialList.

    7. 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).

    0 讨论(0)
提交回复
热议问题