| 1 | // |
| 2 | // typemaps for Ruby |
| 3 | // |
| 4 | // $Header: /cvsroot/swig/SWIG/Lib/ruby/typemaps.i,v 1.7 2005/02/22 23:16:30 marcelomatus Exp $ |
| 5 | // |
| 6 | // Copyright (C) 2000 Network Applied Communication Laboratory, Inc. |
| 7 | // Copyright (C) 2000 Information-technology Promotion Agency, Japan |
| 8 | // |
| 9 | // Masaki Fukushima |
| 10 | // |
| 11 | |
| 12 | /* |
| 13 | The SWIG typemap library provides a language independent mechanism for |
| 14 | supporting output arguments, input values, and other C function |
| 15 | calling mechanisms. The primary use of the library is to provide a |
| 16 | better interface to certain C function--especially those involving |
| 17 | pointers. |
| 18 | */ |
| 19 | |
| 20 | // ------------------------------------------------------------------------ |
| 21 | // Pointer handling |
| 22 | // |
| 23 | // These mappings provide support for input/output arguments and common |
| 24 | // uses for C/C++ pointers. |
| 25 | // ------------------------------------------------------------------------ |
| 26 | |
| 27 | // INPUT typemaps. |
| 28 | // These remap a C pointer to be an "INPUT" value which is passed by value |
| 29 | // instead of reference. |
| 30 | |
| 31 | /* |
| 32 | The following methods can be applied to turn a pointer into a simple |
| 33 | "input" value. That is, instead of passing a pointer to an object, |
| 34 | you would use a real value instead. |
| 35 | |
| 36 | int *INPUT |
| 37 | short *INPUT |
| 38 | long *INPUT |
| 39 | long long *INPUT |
| 40 | unsigned int *INPUT |
| 41 | unsigned short *INPUT |
| 42 | unsigned long *INPUT |
| 43 | unsigned long long *INPUT |
| 44 | unsigned char *INPUT |
| 45 | bool *INPUT |
| 46 | float *INPUT |
| 47 | double *INPUT |
| 48 | |
| 49 | To use these, suppose you had a C function like this : |
| 50 | |
| 51 | double fadd(double *a, double *b) { |
| 52 | return *a+*b; |
| 53 | } |
| 54 | |
| 55 | You could wrap it with SWIG as follows : |
| 56 | |
| 57 | %include typemaps.i |
| 58 | double fadd(double *INPUT, double *INPUT); |
| 59 | |
| 60 | or you can use the %apply directive : |
| 61 | |
| 62 | %include typemaps.i |
| 63 | %apply double *INPUT { double *a, double *b }; |
| 64 | double fadd(double *a, double *b); |
| 65 | |
| 66 | */ |
| 67 | |
| 68 | %define INPUT_TYPEMAP(type, converter) |
| 69 | %typemap(in) type *INPUT($*1_ltype temp), type &INPUT($*1_ltype temp) |
| 70 | { |
| 71 | temp = ($*1_ltype) converter($input); |
| 72 | $1 = &temp; |
| 73 | } |
| 74 | %typemap(typecheck) type *INPUT = type; |
| 75 | %typemap(typecheck) type &INPUT = type; |
| 76 | %enddef |
| 77 | |
| 78 | INPUT_TYPEMAP(float, NUM2DBL); |
| 79 | INPUT_TYPEMAP(double, NUM2DBL); |
| 80 | INPUT_TYPEMAP(int, NUM2INT); |
| 81 | INPUT_TYPEMAP(short, NUM2SHRT); |
| 82 | INPUT_TYPEMAP(long, NUM2LONG); |
| 83 | INPUT_TYPEMAP(long long, NUM2LL); |
| 84 | INPUT_TYPEMAP(unsigned int, NUM2UINT); |
| 85 | INPUT_TYPEMAP(unsigned short, NUM2USHRT); |
| 86 | INPUT_TYPEMAP(unsigned long, NUM2ULONG); |
| 87 | INPUT_TYPEMAP(unsigned long long, NUM2ULL); |
| 88 | INPUT_TYPEMAP(unsigned char, NUM2UINT); |
| 89 | INPUT_TYPEMAP(signed char, NUM2INT); |
| 90 | INPUT_TYPEMAP(bool, RTEST); |
| 91 | |
| 92 | #undef INPUT_TYPEMAP |
| 93 | |
| 94 | // OUTPUT typemaps. These typemaps are used for parameters that |
| 95 | // are output only. The output value is appended to the result as |
| 96 | // a array element. |
| 97 | |
| 98 | /* |
| 99 | The following methods can be applied to turn a pointer into an "output" |
| 100 | value. When calling a function, no input value would be given for |
| 101 | a parameter, but an output value would be returned. In the case of |
| 102 | multiple output values, they are returned in the form of a Ruby Array. |
| 103 | |
| 104 | int *OUTPUT |
| 105 | short *OUTPUT |
| 106 | long *OUTPUT |
| 107 | long long *OUTPUT |
| 108 | unsigned int *OUTPUT |
| 109 | unsigned short *OUTPUT |
| 110 | unsigned long *OUTPUT |
| 111 | unsigned long long *OUTPUT |
| 112 | unsigned char *OUTPUT |
| 113 | bool *OUTPUT |
| 114 | float *OUTPUT |
| 115 | double *OUTPUT |
| 116 | |
| 117 | For example, suppose you were trying to wrap the modf() function in the |
| 118 | C math library which splits x into integral and fractional parts (and |
| 119 | returns the integer part in one of its parameters).K: |
| 120 | |
| 121 | double modf(double x, double *ip); |
| 122 | |
| 123 | You could wrap it with SWIG as follows : |
| 124 | |
| 125 | %include typemaps.i |
| 126 | double modf(double x, double *OUTPUT); |
| 127 | |
| 128 | or you can use the %apply directive : |
| 129 | |
| 130 | %include typemaps.i |
| 131 | %apply double *OUTPUT { double *ip }; |
| 132 | double modf(double x, double *ip); |
| 133 | |
| 134 | The Ruby output of the function would be a Array containing both |
| 135 | output values. |
| 136 | */ |
| 137 | |
| 138 | %include "fragments.i" |
| 139 | |
| 140 | %define OUTPUT_TYPEMAP(type, converter, convtype) |
| 141 | %typemap(in,numinputs=0) type *OUTPUT($*1_ltype temp), type &OUTPUT($*1_ltype temp) "$1 = &temp;"; |
| 142 | %typemap(argout, fragment="output_helper") type *OUTPUT, type &OUTPUT { |
| 143 | VALUE o = converter(convtype (*$1)); |
| 144 | $result = output_helper($result, o); |
| 145 | } |
| 146 | %enddef |
| 147 | |
| 148 | OUTPUT_TYPEMAP(int, INT2NUM, (int)); |
| 149 | OUTPUT_TYPEMAP(short, INT2NUM, (int)); |
| 150 | OUTPUT_TYPEMAP(long, INT2NUM, (long)); |
| 151 | OUTPUT_TYPEMAP(long long, LL2NUM, (long long)); |
| 152 | OUTPUT_TYPEMAP(unsigned int, UINT2NUM, (unsigned int)); |
| 153 | OUTPUT_TYPEMAP(unsigned short, UINT2NUM, (unsigned int)); |
| 154 | OUTPUT_TYPEMAP(unsigned long, UINT2NUM, (unsigned long)); |
| 155 | OUTPUT_TYPEMAP(unsigned long long, ULL2NUM, (unsigned long long)); |
| 156 | OUTPUT_TYPEMAP(unsigned char, UINT2NUM, (unsigned int)); |
| 157 | OUTPUT_TYPEMAP(signed char, INT2NUM, (int)); |
| 158 | OUTPUT_TYPEMAP(float, rb_float_new, (double)); |
| 159 | OUTPUT_TYPEMAP(double, rb_float_new, (double)); |
| 160 | |
| 161 | #undef OUTPUT_TYPEMAP |
| 162 | |
| 163 | %typemap(in,numinputs=0) bool *OUTPUT(bool temp), bool &OUTPUT(bool temp) "$1 = &temp;"; |
| 164 | %typemap(argout, fragment="output_helper") bool *OUTPUT, bool &OUTPUT { |
| 165 | VALUE o = (*$1) ? Qtrue : Qfalse; |
| 166 | $result = output_helper($result, o); |
| 167 | } |
| 168 | |
| 169 | // INOUT |
| 170 | // Mappings for an argument that is both an input and output |
| 171 | // parameter |
| 172 | |
| 173 | /* |
| 174 | The following methods can be applied to make a function parameter both |
| 175 | an input and output value. This combines the behavior of both the |
| 176 | "INPUT" and "OUTPUT" methods described earlier. Output values are |
| 177 | returned in the form of a Ruby array. |
| 178 | |
| 179 | int *INOUT |
| 180 | short *INOUT |
| 181 | long *INOUT |
| 182 | long long *INOUT |
| 183 | unsigned int *INOUT |
| 184 | unsigned short *INOUT |
| 185 | unsigned long *INOUT |
| 186 | unsigned long long *INOUT |
| 187 | unsigned char *INOUT |
| 188 | bool *INOUT |
| 189 | float *INOUT |
| 190 | double *INOUT |
| 191 | |
| 192 | For example, suppose you were trying to wrap the following function : |
| 193 | |
| 194 | void neg(double *x) { |
| 195 | *x = -(*x); |
| 196 | } |
| 197 | |
| 198 | You could wrap it with SWIG as follows : |
| 199 | |
| 200 | %include typemaps.i |
| 201 | void neg(double *INOUT); |
| 202 | |
| 203 | or you can use the %apply directive : |
| 204 | |
| 205 | %include typemaps.i |
| 206 | %apply double *INOUT { double *x }; |
| 207 | void neg(double *x); |
| 208 | |
| 209 | Unlike C, this mapping does not directly modify the input value (since |
| 210 | this makes no sense in Ruby). Rather, the modified input value shows |
| 211 | up as the return value of the function. Thus, to apply this function |
| 212 | to a Ruby variable you might do this : |
| 213 | |
| 214 | x = neg(x) |
| 215 | |
| 216 | Note : previous versions of SWIG used the symbol 'BOTH' to mark |
| 217 | input/output arguments. This is still supported, but will be slowly |
| 218 | phased out in future releases. |
| 219 | |
| 220 | */ |
| 221 | |
| 222 | %typemap(in) int *INOUT = int *INPUT; |
| 223 | %typemap(in) short *INOUT = short *INPUT; |
| 224 | %typemap(in) long *INOUT = long *INPUT; |
| 225 | %typemap(in) long long *INOUT = long long *INPUT; |
| 226 | %typemap(in) unsigned *INOUT = unsigned *INPUT; |
| 227 | %typemap(in) unsigned short *INOUT = unsigned short *INPUT; |
| 228 | %typemap(in) unsigned long *INOUT = unsigned long *INPUT; |
| 229 | %typemap(in) unsigned long long *INOUT = unsigned long long *INPUT; |
| 230 | %typemap(in) unsigned char *INOUT = unsigned char *INPUT; |
| 231 | %typemap(in) signed char *INOUT = signed char *INPUT; |
| 232 | %typemap(in) bool *INOUT = bool *INPUT; |
| 233 | %typemap(in) float *INOUT = float *INPUT; |
| 234 | %typemap(in) double *INOUT = double *INPUT; |
| 235 | |
| 236 | %typemap(in) int &INOUT = int &INPUT; |
| 237 | %typemap(in) short &INOUT = short &INPUT; |
| 238 | %typemap(in) long &INOUT = long &INPUT; |
| 239 | %typemap(in) long long &INOUT = long long &INPUT; |
| 240 | %typemap(in) unsigned &INOUT = unsigned &INPUT; |
| 241 | %typemap(in) unsigned short &INOUT = unsigned short &INPUT; |
| 242 | %typemap(in) unsigned long &INOUT = unsigned long &INPUT; |
| 243 | %typemap(in) unsigned long long &INOUT = unsigned long long &INPUT; |
| 244 | %typemap(in) unsigned char &INOUT = unsigned char &INPUT; |
| 245 | %typemap(in) signed char &INOUT = signed char &INPUT; |
| 246 | %typemap(in) bool &INOUT = bool &INPUT; |
| 247 | %typemap(in) float &INOUT = float &INPUT; |
| 248 | %typemap(in) double &INOUT = double &INPUT; |
| 249 | |
| 250 | %typemap(argout) int *INOUT = int *OUTPUT; |
| 251 | %typemap(argout) short *INOUT = short *OUTPUT; |
| 252 | %typemap(argout) long *INOUT = long *OUTPUT; |
| 253 | %typemap(argout) long long *INOUT = long long *OUTPUT; |
| 254 | %typemap(argout) unsigned *INOUT = unsigned *OUTPUT; |
| 255 | %typemap(argout) unsigned short *INOUT = unsigned short *OUTPUT; |
| 256 | %typemap(argout) unsigned long *INOUT = unsigned long *OUTPUT; |
| 257 | %typemap(argout) unsigned long long *INOUT = unsigned long long *OUTPUT; |
| 258 | %typemap(argout) unsigned char *INOUT = unsigned char *OUTPUT; |
| 259 | %typemap(argout) signed char *INOUT = signed char *OUTPUT; |
| 260 | %typemap(argout) bool *INOUT = bool *OUTPUT; |
| 261 | %typemap(argout) float *INOUT = float *OUTPUT; |
| 262 | %typemap(argout) double *INOUT = double *OUTPUT; |
| 263 | |
| 264 | %typemap(argout) int &INOUT = int &OUTPUT; |
| 265 | %typemap(argout) short &INOUT = short &OUTPUT; |
| 266 | %typemap(argout) long &INOUT = long &OUTPUT; |
| 267 | %typemap(argout) long long &INOUT = long long &OUTPUT; |
| 268 | %typemap(argout) unsigned &INOUT = unsigned &OUTPUT; |
| 269 | %typemap(argout) unsigned short &INOUT = unsigned short &OUTPUT; |
| 270 | %typemap(argout) unsigned long &INOUT = unsigned long &OUTPUT; |
| 271 | %typemap(argout) unsigned long long &INOUT = unsigned long long &OUTPUT; |
| 272 | %typemap(argout) unsigned char &INOUT = unsigned char &OUTPUT; |
| 273 | %typemap(argout) signed char &INOUT = signed char &OUTPUT; |
| 274 | %typemap(argout) bool &INOUT = bool &OUTPUT; |
| 275 | %typemap(argout) float &INOUT = float &OUTPUT; |
| 276 | %typemap(argout) double &INOUT = double &OUTPUT; |
| 277 | |
| 278 | // -------------------------------------------------------------------- |
| 279 | // Special types |
| 280 | // -------------------------------------------------------------------- |
| 281 | |
| 282 | /* |
| 283 | The typemaps.i library also provides the following mappings : |
| 284 | |
| 285 | struct timeval * |
| 286 | time_t |
| 287 | |
| 288 | Ruby has builtin class Time. INPUT/OUTPUT typemap for timeval and |
| 289 | time_t is provided. |
| 290 | |
| 291 | int PROG_ARGC |
| 292 | char **PROG_ARGV |
| 293 | |
| 294 | Some C function receive argc and argv from C main function. |
| 295 | This typemap provides ignore typemap which pass Ruby ARGV contents |
| 296 | as argc and argv to C function. |
| 297 | */ |
| 298 | |
| 299 | |
| 300 | // struct timeval * |
| 301 | %{ |
| 302 | #ifdef __cplusplus |
| 303 | extern "C" { |
| 304 | #endif |
| 305 | #ifdef HAVE_SYS_TIME_H |
| 306 | # include <sys/time.h> |
| 307 | struct timeval rb_time_timeval(VALUE); |
| 308 | #endif |
| 309 | #ifdef __cplusplus |
| 310 | } |
| 311 | #endif |
| 312 | %} |
| 313 | |
| 314 | %typemap(in) struct timeval *INPUT (struct timeval temp) |
| 315 | { |
| 316 | if (NIL_P($input)) |
| 317 | $1 = NULL; |
| 318 | else { |
| 319 | temp = rb_time_timeval($input); |
| 320 | $1 = &temp; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | %typemap(in,numinputs=0) struct timeval *OUTPUT(struct timeval temp) |
| 325 | { |
| 326 | $1 = &temp; |
| 327 | } |
| 328 | |
| 329 | %typemap(argout) struct timeval *OUTPUT |
| 330 | { |
| 331 | $result = rb_time_new($1->tv_sec, $1->tv_usec); |
| 332 | } |
| 333 | |
| 334 | %typemap(out) struct timeval * |
| 335 | { |
| 336 | $result = rb_time_new($1->tv_sec, $1->tv_usec); |
| 337 | } |
| 338 | |
| 339 | %typemap(out) struct timespec * |
| 340 | { |
| 341 | $result = rb_time_new($1->tv_sec, $1->tv_nsec / 1000); |
| 342 | } |
| 343 | |
| 344 | // time_t |
| 345 | %typemap(in) time_t |
| 346 | { |
| 347 | if (NIL_P($input)) |
| 348 | $1 = (time_t)-1; |
| 349 | else |
| 350 | $1 = NUM2LONG(rb_funcall($input, rb_intern("tv_sec"), 0)); |
| 351 | } |
| 352 | |
| 353 | %typemap(out) time_t |
| 354 | { |
| 355 | $result = rb_time_new($1, 0); |
| 356 | } |
| 357 | |
| 358 | // argc and argv |
| 359 | %typemap(in,numinputs=0) int PROG_ARGC { |
| 360 | $1 = RARRAY(rb_argv)->len + 1; |
| 361 | } |
| 362 | |
| 363 | %typemap(in,numinputs=0) char **PROG_ARGV { |
| 364 | int i, n; |
| 365 | VALUE ary = rb_eval_string("[$0] + ARGV"); |
| 366 | n = RARRAY(ary)->len; |
| 367 | $1 = (char **)malloc(n + 1); |
| 368 | for (i = 0; i < n; i++) { |
| 369 | VALUE v = rb_obj_as_string(RARRAY(ary)->ptr[i]); |
| 370 | $1[i] = (char *)malloc(RSTRING(v)->len + 1); |
| 371 | strcpy($1[i], RSTRING(v)->ptr); |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | %typemap(freearg) char **PROG_ARGV { |
| 376 | int i, n = RARRAY(rb_argv)->len + 1; |
| 377 | for (i = 0; i < n; i++) free($1[i]); |
| 378 | free($1); |
| 379 | } |
| 380 | |
| 381 | // FILE * |
| 382 | %{ |
| 383 | #ifdef __cplusplus |
| 384 | extern "C" { |
| 385 | #endif |
| 386 | #include "rubyio.h" |
| 387 | #ifdef __cplusplus |
| 388 | } |
| 389 | #endif |
| 390 | %} |
| 391 | |
| 392 | %typemap(in) FILE *READ { |
| 393 | OpenFile *of; |
| 394 | GetOpenFile($input, of); |
| 395 | rb_io_check_readable(of); |
| 396 | $1 = GetReadFile(of); |
| 397 | rb_read_check($1); |
| 398 | } |
| 399 | |
| 400 | %typemap(in) FILE *READ_NOCHECK { |
| 401 | OpenFile *of; |
| 402 | GetOpenFile($input, of); |
| 403 | rb_io_check_readable(of); |
| 404 | $1 = GetReadFile(of); |
| 405 | } |
| 406 | |
| 407 | %typemap(in) FILE *WRITE { |
| 408 | OpenFile *of; |
| 409 | GetOpenFile($input, of); |
| 410 | rb_io_check_writable(of); |
| 411 | $1 = GetWriteFile(of); |
| 412 | } |
| 413 | |
| 414 | /* Overloading information */ |
| 415 | |
| 416 | %typemap(typecheck) double *INOUT = double; |
| 417 | %typemap(typecheck) signed char *INOUT = signed char; |
| 418 | %typemap(typecheck) unsigned char *INOUT = unsigned char; |
| 419 | %typemap(typecheck) unsigned long *INOUT = unsigned long; |
| 420 | %typemap(typecheck) unsigned long long *INOUT = unsigned long long; |
| 421 | %typemap(typecheck) unsigned short *INOUT = unsigned short; |
| 422 | %typemap(typecheck) unsigned int *INOUT = unsigned int; |
| 423 | %typemap(typecheck) long *INOUT = long; |
| 424 | %typemap(typecheck) long long *INOUT = long long; |
| 425 | %typemap(typecheck) short *INOUT = short; |
| 426 | %typemap(typecheck) int *INOUT = int; |
| 427 | %typemap(typecheck) float *INOUT = float; |
| 428 | |
| 429 | %typemap(typecheck) double &INOUT = double; |
| 430 | %typemap(typecheck) signed char &INOUT = signed char; |
| 431 | %typemap(typecheck) unsigned char &INOUT = unsigned char; |
| 432 | %typemap(typecheck) unsigned long &INOUT = unsigned long; |
| 433 | %typemap(typecheck) unsigned long long &INOUT = unsigned long long; |
| 434 | %typemap(typecheck) unsigned short &INOUT = unsigned short; |
| 435 | %typemap(typecheck) unsigned int &INOUT = unsigned int; |
| 436 | %typemap(typecheck) long &INOUT = long; |
| 437 | %typemap(typecheck) long long &INOUT = long long; |
| 438 | %typemap(typecheck) short &INOUT = short; |
| 439 | %typemap(typecheck) int &INOUT = int; |
| 440 | %typemap(typecheck) float &INOUT = float; |
| 441 | |