Home | History | Annotate | Download | only in java
      1 /* -----------------------------------------------------------------------------
      2  * typemaps.i
      3  *
      4  * Pointer and reference handling typemap library
      5  *
      6  * These mappings provide support for input/output arguments and common
      7  * uses for C/C++ pointers and C++ references.
      8  * ----------------------------------------------------------------------------- */
      9 
     10 /*
     11 INPUT typemaps
     12 --------------
     13 
     14 These typemaps remap a C pointer or C++ reference to be an "INPUT" value which is
     15 passed by value instead of reference.
     16 
     17 The following typemaps can be applied to turn a pointer or reference into a simple
     18 input value.  That is, instead of passing a pointer or reference to an object,
     19 you would use a real value instead.
     20 
     21         bool               *INPUT, bool               &INPUT
     22         signed char        *INPUT, signed char        &INPUT
     23         unsigned char      *INPUT, unsigned char      &INPUT
     24         short              *INPUT, short              &INPUT
     25         unsigned short     *INPUT, unsigned short     &INPUT
     26         int                *INPUT, int                &INPUT
     27         unsigned int       *INPUT, unsigned int       &INPUT
     28         long               *INPUT, long               &INPUT
     29         unsigned long      *INPUT, unsigned long      &INPUT
     30         long long          *INPUT, long long          &INPUT
     31         unsigned long long *INPUT, unsigned long long &INPUT
     32         float              *INPUT, float              &INPUT
     33         double             *INPUT, double             &INPUT
     34 
     35 To use these, suppose you had a C function like this :
     36 
     37         double fadd(double *a, double *b) {
     38                return *a+*b;
     39         }
     40 
     41 You could wrap it with SWIG as follows :
     42 
     43         %include <typemaps.i>
     44         double fadd(double *INPUT, double *INPUT);
     45 
     46 or you can use the %apply directive :
     47 
     48         %include <typemaps.i>
     49         %apply double *INPUT { double *a, double *b };
     50         double fadd(double *a, double *b);
     51 
     52 In Java you could then use it like this:
     53         double answer = modulename.fadd(10.0, 20.0);
     54 
     55 There are no char *INPUT typemaps, however you can apply the signed char * typemaps instead:
     56         %include <typemaps.i>
     57         %apply signed char *INPUT {char *input};
     58         void f(char *input);
     59 */
     60 
     61 %define INPUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JNIDESC)
     62 %typemap(jni) TYPE *INPUT, TYPE &INPUT "JNITYPE"
     63 %typemap(jtype) TYPE *INPUT, TYPE &INPUT "JTYPE"
     64 %typemap(jstype) TYPE *INPUT, TYPE &INPUT "JTYPE"
     65 %typemap(javain) TYPE *INPUT, TYPE &INPUT "$javainput"
     66 
     67 %typemap(in) TYPE *INPUT, TYPE &INPUT
     68 %{ $1 = ($1_ltype)&$input; %}
     69 
     70 %typemap(freearg) TYPE *INPUT, TYPE &INPUT ""
     71 
     72 %typemap(typecheck) TYPE *INPUT = TYPE;
     73 %typemap(typecheck) TYPE &INPUT = TYPE;
     74 %enddef
     75 
     76 INPUT_TYPEMAP(bool, jboolean, boolean, "Z");
     77 INPUT_TYPEMAP(signed char, jbyte, byte, "B");
     78 INPUT_TYPEMAP(unsigned char, jshort, short, "S");
     79 INPUT_TYPEMAP(short, jshort, short, "S");
     80 INPUT_TYPEMAP(unsigned short, jint, int, "I");
     81 INPUT_TYPEMAP(int, jint, int, "I");
     82 INPUT_TYPEMAP(unsigned int, jlong, long, "J");
     83 INPUT_TYPEMAP(long, jint, int, "I");
     84 INPUT_TYPEMAP(unsigned long, jlong, long, "J");
     85 INPUT_TYPEMAP(long long, jlong, long, "J");
     86 INPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, "Ljava/math/BigInteger;");
     87 INPUT_TYPEMAP(float, jfloat, float, "F");
     88 INPUT_TYPEMAP(double, jdouble, double, "D");
     89 
     90 #undef INPUT_TYPEMAP
     91 
     92 /* Convert from BigInteger using the toByteArray member function */
     93 /* Overrides the typemap in the INPUT_TYPEMAP macro */
     94 %typemap(in) unsigned long long *INPUT($*1_ltype temp), unsigned long long &INPUT($*1_ltype temp) {
     95   jclass clazz;
     96   jmethodID mid;
     97   jbyteArray ba;
     98   jbyte* bae;
     99   jsize sz;
    100   int i;
    101 
    102   if (!$input) {
    103     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "BigInteger null");
    104     return $null;
    105   }
    106   clazz = JCALL1(GetObjectClass, jenv, $input);
    107   mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
    108   ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, $input, mid);
    109   bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
    110   sz = JCALL1(GetArrayLength, jenv, ba);
    111   temp = 0;
    112   for(i=0; i<sz; i++) {
    113     temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
    114   }
    115   JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
    116   $1 = &temp;
    117 }
    118 
    119 // OUTPUT typemaps.   These typemaps are used for parameters that
    120 // are output only.   An array replaces the c pointer or reference parameter.
    121 // The output value is returned in this array passed in.
    122 
    123 /*
    124 OUTPUT typemaps
    125 ---------------
    126 
    127 The following typemaps can be applied to turn a pointer or reference into an "output"
    128 value.  When calling a function, no input value would be given for
    129 a parameter, but an output value would be returned.  This works by a
    130 Java array being passed as a parameter where a c pointer or reference is required.
    131 As with any Java function, the array is passed by reference so that
    132 any modifications to the array will be picked up in the calling function.
    133 Note that the array passed in MUST have at least one element, but as the
    134 c function does not require any input, the value can be set to anything.
    135 
    136         bool               *OUTPUT, bool               &OUTPUT
    137         signed char        *OUTPUT, signed char        &OUTPUT
    138         unsigned char      *OUTPUT, unsigned char      &OUTPUT
    139         short              *OUTPUT, short              &OUTPUT
    140         unsigned short     *OUTPUT, unsigned short     &OUTPUT
    141         int                *OUTPUT, int                &OUTPUT
    142         unsigned int       *OUTPUT, unsigned int       &OUTPUT
    143         long               *OUTPUT, long               &OUTPUT
    144         unsigned long      *OUTPUT, unsigned long      &OUTPUT
    145         long long          *OUTPUT, long long          &OUTPUT
    146         unsigned long long *OUTPUT, unsigned long long &OUTPUT
    147         float              *OUTPUT, float              &OUTPUT
    148         double             *OUTPUT, double             &OUTPUT
    149 
    150 For example, suppose you were trying to wrap the modf() function in the
    151 C math library which splits x into integral and fractional parts (and
    152 returns the integer part in one of its parameters):
    153 
    154         double modf(double x, double *ip);
    155 
    156 You could wrap it with SWIG as follows :
    157 
    158         %include <typemaps.i>
    159         double modf(double x, double *OUTPUT);
    160 
    161 or you can use the %apply directive :
    162 
    163         %include <typemaps.i>
    164         %apply double *OUTPUT { double *ip };
    165         double modf(double x, double *ip);
    166 
    167 The Java output of the function would be the function return value and the
    168 value in the single element array. In Java you would use it like this:
    169 
    170     double[] ptr = {0.0};
    171     double fraction = modulename.modf(5.0,ptr);
    172 
    173 There are no char *OUTPUT typemaps, however you can apply the signed char * typemaps instead:
    174         %include <typemaps.i>
    175         %apply signed char *OUTPUT {char *output};
    176         void f(char *output);
    177 */
    178 
    179 /* Java BigInteger[] */
    180 %typecheck(SWIG_TYPECHECK_INT128_ARRAY) SWIGBIGINTEGERARRAY ""
    181 
    182 %define OUTPUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JAVATYPE, JNIDESC, TYPECHECKTYPE)
    183 %typemap(jni) TYPE *OUTPUT, TYPE &OUTPUT %{JNITYPE##Array%}
    184 %typemap(jtype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]"
    185 %typemap(jstype) TYPE *OUTPUT, TYPE &OUTPUT "JTYPE[]"
    186 %typemap(javain) TYPE *OUTPUT, TYPE &OUTPUT "$javainput"
    187 
    188 %typemap(in) TYPE *OUTPUT($*1_ltype temp), TYPE &OUTPUT($*1_ltype temp)
    189 {
    190   if (!$input) {
    191     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    192     return $null;
    193   }
    194   if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    195     SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    196     return $null;
    197   }
    198   temp = ($*1_ltype)0;
    199   $1 = &temp;
    200 }
    201 
    202 %typemap(freearg) TYPE *OUTPUT, TYPE &OUTPUT ""
    203 
    204 %typemap(argout) TYPE *OUTPUT, TYPE &OUTPUT
    205 {
    206   JNITYPE jvalue = (JNITYPE)temp$argnum;
    207   JCALL4(Set##JAVATYPE##ArrayRegion, jenv, $input, 0, 1, &jvalue);
    208 }
    209 
    210 %typemap(typecheck) TYPE *OUTPUT = TYPECHECKTYPE;
    211 %typemap(typecheck) TYPE &OUTPUT = TYPECHECKTYPE;
    212 %enddef
    213 
    214 OUTPUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Ljava/lang/Boolean;", jbooleanArray);
    215 OUTPUT_TYPEMAP(signed char, jbyte, byte, Byte, "[Ljava/lang/Byte;", jbyteArray);
    216 OUTPUT_TYPEMAP(unsigned char, jshort, short, Short, "[Ljava/lang/Short;", jshortArray);
    217 OUTPUT_TYPEMAP(short, jshort, short, Short, "[Ljava/lang/Short;", jshortArray);
    218 OUTPUT_TYPEMAP(unsigned short, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    219 OUTPUT_TYPEMAP(int, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    220 OUTPUT_TYPEMAP(unsigned int, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    221 OUTPUT_TYPEMAP(long, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    222 OUTPUT_TYPEMAP(unsigned long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    223 OUTPUT_TYPEMAP(long long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    224 OUTPUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, NOTUSED, "[Ljava/lang/BigInteger;", SWIGBIGINTEGERARRAY);
    225 OUTPUT_TYPEMAP(float, jfloat, float, Float, "[Ljava/lang/Float;", jfloatArray);
    226 OUTPUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleArray);
    227 
    228 #undef OUTPUT_TYPEMAP
    229 
    230 %typemap(in) bool *OUTPUT($*1_ltype temp), bool &OUTPUT($*1_ltype temp)
    231 {
    232   if (!$input) {
    233     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    234     return $null;
    235   }
    236   if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    237     SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    238     return $null;
    239   }
    240   temp = false;
    241   $1 = &temp;
    242 }
    243 
    244 /* Convert to BigInteger - byte array holds number in 2's complement big endian format */
    245 /* Use first element in BigInteger array for output */
    246 /* Overrides the typemap in the OUTPUT_TYPEMAP macro */
    247 %typemap(argout) unsigned long long *OUTPUT, unsigned long long &OUTPUT {
    248   jbyteArray ba = JCALL1(NewByteArray, jenv, 9);
    249   jbyte* bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
    250   jclass clazz = JCALL1(FindClass, jenv, "java/math/BigInteger");
    251   jmethodID mid = JCALL3(GetMethodID, jenv, clazz, "<init>", "([B)V");
    252   jobject bigint;
    253   int i;
    254 
    255   bae[0] = 0;
    256   for(i=1; i<9; i++ ) {
    257     bae[i] = (jbyte)(temp$argnum>>8*(8-i));
    258   }
    259 
    260   JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
    261   bigint = JCALL3(NewObject, jenv, clazz, mid, ba);
    262   JCALL3(SetObjectArrayElement, jenv, $input, 0, bigint);
    263 }
    264 
    265 /*
    266 INOUT typemaps
    267 --------------
    268 
    269 Mappings for a parameter that is both an input and an output parameter
    270 
    271 The following typemaps can be applied to make a function parameter both
    272 an input and output value.  This combines the behavior of both the
    273 "INPUT" and "OUTPUT" typemaps described earlier.  Output values are
    274 returned as an element in a Java array.
    275 
    276         bool               *INOUT, bool               &INOUT
    277         signed char        *INOUT, signed char        &INOUT
    278         unsigned char      *INOUT, unsigned char      &INOUT
    279         short              *INOUT, short              &INOUT
    280         unsigned short     *INOUT, unsigned short     &INOUT
    281         int                *INOUT, int                &INOUT
    282         unsigned int       *INOUT, unsigned int       &INOUT
    283         long               *INOUT, long               &INOUT
    284         unsigned long      *INOUT, unsigned long      &INOUT
    285         long long          *INOUT, long long          &INOUT
    286         unsigned long long *INOUT, unsigned long long &INOUT
    287         float              *INOUT, float              &INOUT
    288         double             *INOUT, double             &INOUT
    289 
    290 For example, suppose you were trying to wrap the following function :
    291 
    292         void neg(double *x) {
    293              *x = -(*x);
    294         }
    295 
    296 You could wrap it with SWIG as follows :
    297 
    298         %include <typemaps.i>
    299         void neg(double *INOUT);
    300 
    301 or you can use the %apply directive :
    302 
    303         %include <typemaps.i>
    304         %apply double *INOUT { double *x };
    305         void neg(double *x);
    306 
    307 This works similarly to C in that the mapping directly modifies the
    308 input value - the input must be an array with a minimum of one element.
    309 The element in the array is the input and the output is the element in
    310 the array.
    311 
    312        double x[] = {5.0};
    313        neg(x);
    314 
    315 The implementation of the OUTPUT and INOUT typemaps is different to other
    316 languages in that other languages will return the output value as part
    317 of the function return value. This difference is due to Java being a typed language.
    318 
    319 There are no char *INOUT typemaps, however you can apply the signed char * typemaps instead:
    320         %include <typemaps.i>
    321         %apply signed char *INOUT {char *inout};
    322         void f(char *inout);
    323 */
    324 
    325 %define INOUT_TYPEMAP(TYPE, JNITYPE, JTYPE, JAVATYPE, JNIDESC, TYPECHECKTYPE)
    326 %typemap(jni) TYPE *INOUT, TYPE &INOUT %{JNITYPE##Array%}
    327 %typemap(jtype) TYPE *INOUT, TYPE &INOUT "JTYPE[]"
    328 %typemap(jstype) TYPE *INOUT, TYPE &INOUT "JTYPE[]"
    329 %typemap(javain) TYPE *INOUT, TYPE &INOUT "$javainput"
    330 
    331 %typemap(in) TYPE *INOUT, TYPE &INOUT {
    332   if (!$input) {
    333     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    334     return $null;
    335   }
    336   if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    337     SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    338     return $null;
    339   }
    340   $1 = ($1_ltype) JCALL2(Get##JAVATYPE##ArrayElements, jenv, $input, 0);
    341 }
    342 
    343 %typemap(freearg) TYPE *INOUT, TYPE &INOUT ""
    344 
    345 %typemap(argout) TYPE *INOUT, TYPE &INOUT
    346 { JCALL3(Release##JAVATYPE##ArrayElements, jenv, $input, (JNITYPE *)$1, 0); }
    347 
    348 
    349 %typemap(typecheck) TYPE *INOUT = TYPECHECKTYPE;
    350 %typemap(typecheck) TYPE &INOUT = TYPECHECKTYPE;
    351 %enddef
    352 
    353 INOUT_TYPEMAP(bool, jboolean, boolean, Boolean, "[Ljava/lang/Boolean;", jbooleanArray);
    354 INOUT_TYPEMAP(signed char, jbyte, byte, Byte, "[Ljava/lang/Byte;", jbyteArray);
    355 INOUT_TYPEMAP(unsigned char, jshort, short, Short, "[Ljava/lang/Short;", jshortArray);
    356 INOUT_TYPEMAP(short, jshort, short, Short, "[Ljava/lang/Short;", jshortArray);
    357 INOUT_TYPEMAP(unsigned short, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    358 INOUT_TYPEMAP(int, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    359 INOUT_TYPEMAP(unsigned int, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    360 INOUT_TYPEMAP(long, jint, int, Int, "[Ljava/lang/Integer;", jintArray);
    361 INOUT_TYPEMAP(unsigned long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    362 INOUT_TYPEMAP(long long, jlong, long, Long, "[Ljava/lang/Long;", jlongArray);
    363 INOUT_TYPEMAP(unsigned long long, jobject, java.math.BigInteger, NOTUSED, "[Ljava.math.BigInteger;", SWIGBIGINTEGERARRAY);
    364 INOUT_TYPEMAP(float, jfloat, float, Float, "[Ljava/lang/Float;", jfloatArray);
    365 INOUT_TYPEMAP(double, jdouble, double, Double, "[Ljava/lang/Double;", jdoubleArray);
    366 
    367 #undef INOUT_TYPEMAP
    368 
    369 /* Override typemaps in the INOUT_TYPEMAP macro for booleans to fix casts
    370    as a jboolean isn't always the same size as a bool */
    371 %typemap(in) bool *INOUT (bool btemp, jboolean *jbtemp), bool &INOUT (bool btemp, jboolean *jbtemp) {
    372   if (!$input) {
    373     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    374     return $null;
    375   }
    376   if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    377     SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    378     return $null;
    379   }
    380   jbtemp = JCALL2(GetBooleanArrayElements, jenv, $input, 0);
    381   btemp = (*jbtemp) ? true : false;
    382   $1 = &btemp;
    383 }
    384 
    385 %typemap(argout) bool *INOUT, bool &INOUT {
    386   *jbtemp$argnum = btemp$argnum ? (jboolean)1 : (jboolean)0;
    387   JCALL3(ReleaseBooleanArrayElements, jenv, $input , (jboolean *)jbtemp$argnum, 0);
    388 }
    389 
    390 /* Override the typemap in the INOUT_TYPEMAP macro for unsigned long long */
    391 %typemap(in) unsigned long long *INOUT ($*1_ltype temp), unsigned long long &INOUT ($*1_ltype temp) {
    392   jobject bigint;
    393   jclass clazz;
    394   jmethodID mid;
    395   jbyteArray ba;
    396   jbyte* bae;
    397   jsize sz;
    398   int i;
    399 
    400   if (!$input) {
    401     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
    402     return $null;
    403   }
    404   if (JCALL1(GetArrayLength, jenv, $input) == 0) {
    405     SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
    406     return $null;
    407   }
    408   bigint = JCALL2(GetObjectArrayElement, jenv, $input, 0);
    409   if (!bigint) {
    410     SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array element null");
    411     return $null;
    412   }
    413   clazz = JCALL1(GetObjectClass, jenv, bigint);
    414   mid = JCALL3(GetMethodID, jenv, clazz, "toByteArray", "()[B");
    415   ba = (jbyteArray)JCALL2(CallObjectMethod, jenv, bigint, mid);
    416   bae = JCALL2(GetByteArrayElements, jenv, ba, 0);
    417   sz = JCALL1(GetArrayLength, jenv, ba);
    418   temp = 0;
    419   for(i=0; i<sz; i++) {
    420     temp = (temp << 8) | ($*1_ltype)(unsigned char)bae[i];
    421   }
    422   JCALL3(ReleaseByteArrayElements, jenv, ba, bae, 0);
    423   $1 = &temp;
    424 }
    425 
    426 %typemap(argout) unsigned long long *INOUT = unsigned long long *OUTPUT;
    427 %typemap(argout) unsigned long long &INOUT = unsigned long long &OUTPUT;
    428