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