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