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