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