1 /* ----------------------------------------------------------------------------- 2 * list_vector.i 3 * 4 * Guile typemaps for converting between arrays and Scheme lists or vectors 5 * ----------------------------------------------------------------------------- */ 6 7 /* Here is a macro that will define typemaps for converting between C 8 arrays and Scheme lists or vectors when passing arguments to the C 9 function. 10 11 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(C_TYPE, SCM_TO_C, C_TO_SCM, SCM_TYPE) 12 13 Supported calling conventions: 14 15 func(int VECTORLENINPUT, [const] C_TYPE *VECTORINPUT) 16 17 Scheme wrapper will take one argument, a vector. A temporary C 18 array of elements of type C_TYPE will be allocated and filled 19 with the elements of the vectors, converted to C with the 20 SCM_TO_C function. Length and address of the array are passed 21 to the C function. 22 23 SCM_TYPE is used to describe the Scheme type of the elements in 24 the Guile procedure documentation. 25 26 func(int LISTLENINPUT, [const] C_TYPE *LISTINPUT) 27 28 Likewise, but the Scheme wrapper will take one argument, a list. 29 30 func(int *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT) 31 32 Scheme wrapper will take no arguments. Addresses of an integer 33 and a C_TYPE * variable will be passed to the C function. The 34 C function is expected to return address and length of a 35 freshly allocated array of elements of type C_TYPE through 36 these pointers. The elements of this array are converted to 37 Scheme with the C_TO_SCM function and returned as a Scheme 38 vector. 39 40 If the function has a void return value, the vector constructed 41 by this typemap becomes the return value of the Scheme wrapper. 42 Otherwise, the function returns multiple values. (See 43 the documentation on how to deal with multiple values.) 44 45 func(int *LISTLENOUTPUT, C_TYPE **LISTOUTPUT) 46 47 Likewise, but the Scheme wrapper will return a list instead of 48 a vector. 49 50 It is also allowed to use "size_t LISTLENINPUT" rather than "int 51 LISTLENINPUT". */ 52 53 %define TYPEMAP_LIST_VECTOR_INPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, SCM_TYPE) 54 55 /* input */ 56 57 /* We make use of the new multi-dispatch typemaps here. */ 58 59 %typemap(in, doc="$NAME is a vector of " #SCM_TYPE " values") 60 (int VECTORLENINPUT, C_TYPE *VECTORINPUT), 61 (size_t VECTORLENINPUT, C_TYPE *VECTORINPUT) 62 { 63 SCM_VALIDATE_VECTOR($argnum, $input); 64 $1 = scm_c_vector_length($input); 65 if ($1 > 0) { 66 $1_ltype i; 67 $2 = (C_TYPE *) SWIG_malloc(sizeof(C_TYPE) * $1); 68 for (i = 0; i<$1; i++) { 69 SCM swig_scm_value = scm_vector_ref($input, scm_from_long(i)); 70 $2[i] = SCM_TO_C_EXPR; 71 } 72 } 73 else $2 = NULL; 74 } 75 76 %typemap(in, doc="$NAME is a list of " #SCM_TYPE " values") 77 (int LISTLENINPUT, C_TYPE *LISTINPUT), 78 (size_t LISTLENINPUT, C_TYPE *LISTINPUT) 79 { 80 SCM_VALIDATE_LIST($argnum, $input); 81 $1 = scm_to_ulong(scm_length($input)); 82 if ($1 > 0) { 83 $1_ltype i; 84 SCM rest; 85 $2 = (C_TYPE *) SWIG_malloc(sizeof(C_TYPE) * $1); 86 for (i = 0, rest = $input; 87 i<$1; 88 i++, rest = SCM_CDR(rest)) { 89 SCM swig_scm_value = SCM_CAR(rest); 90 $2[i] = SCM_TO_C_EXPR; 91 } 92 } 93 else $2 = NULL; 94 } 95 96 /* Do not check for NULL pointers (override checks). */ 97 98 %typemap(check) (int VECTORLENINPUT, C_TYPE *VECTORINPUT), 99 (size_t VECTORLENINPUT, C_TYPE *VECTORINPUT), 100 (int LISTLENINPUT, C_TYPE *LISTINPUT), 101 (size_t LISTLENINPUT, C_TYPE *LISTINPUT) 102 "/* no check for NULL pointer */"; 103 104 /* Discard the temporary array after the call. */ 105 106 %typemap(freearg) (int VECTORLENINPUT, C_TYPE *VECTORINPUT), 107 (size_t VECTORLENINPUT, C_TYPE *VECTORINPUT), 108 (int LISTLENINPUT, C_TYPE *LISTINPUT), 109 (size_t LISTLENINPUT, C_TYPE *LISTINPUT) 110 {if ($2!=NULL) SWIG_free($2);} 111 112 %enddef 113 114 /* output */ 115 116 %define TYPEMAP_LIST_VECTOR_OUTPUT_WITH_EXPR(C_TYPE, C_TO_SCM_EXPR, SCM_TYPE) 117 118 /* First we make temporary variables ARRAYLENTEMP and ARRAYTEMP, 119 whose addresses we pass to the C function. We ignore both 120 arguments for Scheme. */ 121 122 %typemap(in,numinputs=0) (int *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT) 123 (int arraylentemp, C_TYPE *arraytemp), 124 (int *LISTLENOUTPUT, C_TYPE **LISTOUTPUT) 125 (int arraylentemp, C_TYPE *arraytemp), 126 (size_t *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT) 127 (size_t arraylentemp, C_TYPE *arraytemp), 128 (size_t *LISTLENOUTPUT, C_TYPE **LISTOUTPUT) 129 (size_t arraylentemp, C_TYPE *arraytemp) 130 %{ 131 $1 = &arraylentemp; 132 $2 = &arraytemp; 133 %} 134 135 /* In the ARGOUT typemaps, we convert the array into a vector or 136 a list and append it to the results. */ 137 138 %typemap(argout, doc="$NAME (a vector of " #SCM_TYPE " values)") 139 (int *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT), 140 (size_t *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT) 141 { 142 $*1_ltype i; 143 SCM res = scm_make_vector(scm_from_long(*$1), 144 SCM_BOOL_F); 145 for (i = 0; i<*$1; i++) { 146 C_TYPE swig_c_value = (*$2)[i]; 147 SCM elt = C_TO_SCM_EXPR; 148 scm_vector_set_x(res, scm_from_long(i), elt); 149 } 150 SWIG_APPEND_VALUE(res); 151 } 152 153 %typemap(argout, doc="$NAME (a list of " #SCM_TYPE " values)") 154 (int *LISTLENOUTPUT, C_TYPE **LISTOUTPUT), 155 (size_t *LISTLENOUTPUT, C_TYPE **LISTOUTPUT) 156 { 157 int i; 158 SCM res = SCM_EOL; 159 for (i = ((int)(*$1)) - 1; i>=0; i--) { 160 C_TYPE swig_c_value = (*$2)[i]; 161 SCM elt = C_TO_SCM_EXPR; 162 res = scm_cons(elt, res); 163 } 164 SWIG_APPEND_VALUE(res); 165 } 166 167 /* In the FREEARG typemaps, get rid of the C vector. 168 (This can be overridden if you want to keep the C vector.) */ 169 170 %typemap(freearg) 171 (int *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT), 172 (size_t *VECTORLENOUTPUT, C_TYPE **VECTOROUTPUT), 173 (int *LISTLENOUTPUT, C_TYPE **LISTOUTPUT), 174 (size_t *LISTLENOUTPUT, C_TYPE **LISTOUTPUT) 175 { 176 if ((*$2)!=NULL) free(*$2); 177 } 178 179 %enddef 180 181 %define TYPEMAP_LIST_VECTOR_INPUT_OUTPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, C_TO_SCM_EXPR, SCM_TYPE) 182 TYPEMAP_LIST_VECTOR_INPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, SCM_TYPE) 183 TYPEMAP_LIST_VECTOR_OUTPUT_WITH_EXPR(C_TYPE, C_TO_SCM_EXPR, SCM_TYPE) 184 %enddef 185 186 %define TYPEMAP_LIST_VECTOR_INPUT(C_TYPE, SCM_TO_C, SCM_TYPE) 187 TYPEMAP_LIST_VECTOR_INPUT_WITH_EXPR 188 (C_TYPE, SCM_TO_C(swig_scm_value), SCM_TYPE) 189 %enddef 190 191 %define TYPEMAP_LIST_VECTOR_OUTPUT(C_TYPE, C_TO_SCM, SCM_TYPE) 192 TYPEMAP_LIST_VECTOR_OUTPUT_WITH_EXPR 193 (C_TYPE, C_TO_SCM(swig_c_value), SCM_TYPE) 194 %enddef 195 196 %define TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(C_TYPE, SCM_TO_C, C_TO_SCM, SCM_TYPE) 197 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT_WITH_EXPR 198 (C_TYPE, SCM_TO_C(swig_scm_value), C_TO_SCM(swig_c_value), SCM_TYPE) 199 %enddef 200 201 /* We use the macro to define typemaps for some standard types. */ 202 203 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(bool, scm_is_true, scm_from_bool, boolean); 204 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(char, SCM_CHAR, SCM_MAKE_CHAR, char); 205 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned char, SCM_CHAR, SCM_MAKE_CHAR, char); 206 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(int, scm_to_int, scm_from_long, integer); 207 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(short, scm_to_int, scm_from_long, integer); 208 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(long, scm_to_long, scm_from_long, integer); 209 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(ptrdiff_t, scm_to_long, scm_from_long, integer); 210 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned int, scm_to_ulong, scm_from_ulong, integer); 211 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned short, scm_to_ulong, scm_from_ulong, integer); 212 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned long, scm_to_ulong, scm_from_ulong, integer); 213 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(size_t, scm_to_ulong, scm_from_ulong, integer); 214 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(float, scm_to_double, scm_from_double, real); 215 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(double, scm_to_double, scm_from_double, real); 216 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(char *, SWIG_scm2str, SWIG_str02scm, string); 217 TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(const char *, SWIG_scm2str, SWIG_str02scm, string); 218 219 /* For the char *, free all strings after converting */ 220 221 %typemap(freearg) 222 (int *VECTORLENOUTPUT, char ***VECTOROUTPUT), 223 (size_t *VECTORLENOUTPUT, char ***VECTOROUTPUT), 224 (int *LISTLENOUTPUT, char ***LISTOUTPUT), 225 (size_t *LISTLENOUTPUT, char ***LISTOUTPUT), 226 (int *VECTORLENOUTPUT, const char ***VECTOROUTPUT), 227 (size_t *VECTORLENOUTPUT, const char ***VECTOROUTPUT), 228 (int *LISTLENOUTPUT, const char ***LISTOUTPUT), 229 (size_t *LISTLENOUTPUT, const char ***LISTOUTPUT) 230 { 231 if ((*$2)!=NULL) { 232 int i; 233 for (i = 0; i < *$1; i++) { 234 if ((*$2)[i] != NULL) free((*$2)[i]); 235 } 236 free(*$2); 237 } 238 } 239 240 %typemap(freearg) (int VECTORLENINPUT, char **VECTORINPUT), 241 (size_t VECTORLENINPUT, char **VECTORINPUT), 242 (int LISTLENINPUT, char **LISTINPUT), 243 (size_t LISTLENINPUT, char **LISTINPUT), 244 (int VECTORLENINPUT, const char **VECTORINPUT), 245 (size_t VECTORLENINPUT, const char **VECTORINPUT), 246 (int LISTLENINPUT, const char **LISTINPUT), 247 (size_t LISTLENINPUT, const char **LISTINPUT) 248 { 249 if (($2)!=NULL) { 250 int i; 251 for (i = 0; i< $1; i++) 252 if (($2)[i] != NULL) free(($2)[i]); 253 free($2); 254 } 255 } 256 257 258 /* Following is a macro that emits typemaps that are much more 259 flexible. (They are also messier.) It supports multiple parallel 260 lists and vectors (sharing one length argument each). 261 262 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(C_TYPE, SCM_TO_C, C_TO_SCM, SCM_TYPE) 263 264 Supported calling conventions: 265 266 func(int PARALLEL_VECTORLENINPUT, [const] C_TYPE *PARALLEL_VECTORINPUT, ...) or 267 func([const] C_TYPE *PARALLEL_VECTORINPUT, ..., int PARALLEL_VECTORLENINPUT) 268 269 func(int PARALLEL_LISTLENINPUT, [const] C_TYPE *PARALLEL_LISTINPUT, ...) or 270 func([const] C_TYPE *PARALLEL_LISTINPUT, ..., int PARALLEL_LISTLENINPUT) 271 272 func(int *PARALLEL_VECTORLENOUTPUT, C_TYPE **PARALLEL_VECTOROUTPUT, ...) or 273 func(C_TYPE **PARALLEL_VECTOROUTPUT, int *PARALLEL_VECTORLENOUTPUT, ...) 274 275 func(int *PARALLEL_LISTLENOUTPUT, C_TYPE **PARALLEL_LISTOUTPUT) or 276 func(C_TYPE **PARALLEL_LISTOUTPUT, int *PARALLEL_LISTLENOUTPUT) 277 278 It is also allowed to use "size_t PARALLEL_LISTLENINPUT" rather than "int 279 PARALLEL_LISTLENINPUT". */ 280 281 %define TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, SCM_TYPE) 282 283 /* input */ 284 285 /* Passing data is a little complicated here; just remember: 286 IGNORE typemaps come first, then IN, then CHECK. But if 287 IGNORE is given, IN won't be used for this type. 288 289 We need to "ignore" one of the parameters because there shall 290 be only one argument on the Scheme side. Here we only 291 initialize the array length to 0 but save its address for a 292 later change. */ 293 294 %typemap(in,numinputs=0) int PARALLEL_VECTORLENINPUT (int *_global_vector_length), 295 size_t PARALLEL_VECTORLENINPUT (size_t *_global_vector_length) 296 { 297 $1 = 0; 298 _global_vector_length = &$1; 299 } 300 301 %typemap(in,numinputs=0) int PARALLEL_LISTLENINPUT (int *_global_list_length), 302 size_t PARALLEL_LISTLENINPUT (size_t *_global_list_length) 303 { 304 $1 = 0; 305 _global_list_length = &$1; 306 } 307 308 /* All the work is done in IN. */ 309 310 %typemap(in, doc="$NAME is a vector of " #SCM_TYPE " values") 311 C_TYPE *PARALLEL_VECTORINPUT, 312 const C_TYPE *PARALLEL_VECTORINPUT 313 { 314 SCM_VALIDATE_VECTOR($argnum, $input); 315 *_global_vector_length = scm_c_vector_length($input); 316 if (*_global_vector_length > 0) { 317 int i; 318 $1 = (C_TYPE *) SWIG_malloc(sizeof(C_TYPE) 319 * (*_global_vector_length)); 320 for (i = 0; i<*_global_vector_length; i++) { 321 SCM swig_scm_value = scm_vector_ref($input, scm_from_long(i)); 322 $1[i] = SCM_TO_C_EXPR; 323 } 324 } 325 else $1 = NULL; 326 } 327 328 %typemap(in, doc="$NAME is a list of " #SCM_TYPE " values") 329 C_TYPE *PARALLEL_LISTINPUT, 330 const C_TYPE *PARALLEL_LISTINPUT 331 { 332 SCM_VALIDATE_LIST($argnum, $input); 333 *_global_list_length = scm_to_ulong(scm_length($input)); 334 if (*_global_list_length > 0) { 335 int i; 336 SCM rest; 337 $1 = (C_TYPE *) SWIG_malloc(sizeof(C_TYPE) 338 * (*_global_list_length)); 339 for (i = 0, rest = $input; 340 i<*_global_list_length; 341 i++, rest = SCM_CDR(rest)) { 342 SCM swig_scm_value = SCM_CAR(rest); 343 $1[i] = SCM_TO_C_EXPR; 344 } 345 } 346 else $1 = NULL; 347 } 348 349 /* Don't check for NULL pointers (override checks). */ 350 351 %typemap(check) C_TYPE *PARALLEL_VECTORINPUT, 352 const C_TYPE *PARALLEL_VECTORINPUT, 353 C_TYPE *PARALLEL_LISTINPUT, 354 const C_TYPE *PARALLEL_LISTINPUT 355 "/* no check for NULL pointer */"; 356 357 /* Discard the temporary array after the call. */ 358 359 %typemap(freearg) C_TYPE *PARALLEL_VECTORINPUT, 360 const C_TYPE *PARALLEL_VECTORINPUT, 361 C_TYPE *PARALLEL_LISTINPUT, 362 const C_TYPE *PARALLEL_LISTINPUT 363 {if ($1!=NULL) SWIG_free($1);} 364 365 %enddef 366 367 %define TYPEMAP_PARALLEL_LIST_VECTOR_OUTPUT_WITH_EXPR(C_TYPE, C_TO_SCM_EXPR, SCM_TYPE) 368 369 /* output */ 370 371 /* First we make a temporary variable ARRAYLENTEMP, use its 372 address as the ...LENOUTPUT argument for the C function and 373 "ignore" the ...LENOUTPUT argument for Scheme. */ 374 375 %typemap(in,numinputs=0) int *PARALLEL_VECTORLENOUTPUT (int _global_arraylentemp), 376 size_t *PARALLEL_VECTORLENOUTPUT (size_t _global_arraylentemp), 377 int *PARALLEL_LISTLENOUTPUT (int _global_arraylentemp), 378 size_t *PARALLEL_LISTLENOUTPUT (size_t _global_arraylentemp) 379 "$1 = &_global_arraylentemp;"; 380 381 /* We also need to ignore the ...OUTPUT argument. */ 382 383 %typemap(in,numinputs=0) C_TYPE **PARALLEL_VECTOROUTPUT (C_TYPE *arraytemp), 384 C_TYPE **PARALLEL_LISTOUTPUT (C_TYPE *arraytemp) 385 "$1 = &arraytemp;"; 386 387 /* In the ARGOUT typemaps, we convert the array into a vector or 388 a list and append it to the results. */ 389 390 %typemap(argout, doc="$NAME (a vector of " #SCM_TYPE " values)") 391 C_TYPE **PARALLEL_VECTOROUTPUT 392 { 393 int i; 394 SCM res = scm_make_vector(scm_from_long(_global_arraylentemp), 395 SCM_BOOL_F); 396 for (i = 0; i<_global_arraylentemp; i++) { 397 C_TYPE swig_c_value = (*$1)[i]; 398 SCM elt = C_TO_SCM_EXPR; 399 scm_vector_set_x(res, scm_from_long(i), elt); 400 } 401 SWIG_APPEND_VALUE(res); 402 } 403 404 %typemap(argout, doc="$NAME (a list of " #SCM_TYPE " values)") 405 C_TYPE **PARALLEL_LISTOUTPUT 406 { 407 int i; 408 SCM res = SCM_EOL; 409 if (_global_arraylentemp > 0) { 410 for (i = _global_arraylentemp - 1; i>=0; i--) { 411 C_TYPE swig_c_value = (*$1)[i]; 412 SCM elt = C_TO_SCM_EXPR; 413 res = scm_cons(elt, res); 414 } 415 } 416 SWIG_APPEND_VALUE(res); 417 } 418 419 /* In the FREEARG typemaps, get rid of the C vector. 420 (This can be overridden if you want to keep the C vector.) */ 421 422 %typemap(freearg) C_TYPE **PARALLEL_VECTOROUTPUT, 423 C_TYPE **PARALLEL_LISTOUTPUT 424 { 425 if ((*$1)!=NULL) free(*$1); 426 } 427 428 %enddef 429 430 %define TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, C_TO_SCM_EXPR, SCM_TYPE) 431 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_WITH_EXPR(C_TYPE, SCM_TO_C_EXPR, SCM_TYPE) 432 TYPEMAP_PARALLEL_LIST_VECTOR_OUTPUT_WITH_EXPR(C_TYPE, C_TO_SCM_EXPR, SCM_TYPE) 433 %enddef 434 435 %define TYPEMAP_PARALLEL_LIST_VECTOR_INPUT(C_TYPE, SCM_TO_C, SCM_TYPE) 436 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_WITH_EXPR 437 (C_TYPE, SCM_TO_C(swig_scm_value), SCM_TYPE) 438 %enddef 439 440 %define TYPEMAP_PARALLEL_LIST_VECTOR_OUTPUT(C_TYPE, C_TO_SCM, SCM_TYPE) 441 TYPEMAP_PARALLEL_LIST_VECTOR_OUTPUT_WITH_EXPR 442 (C_TYPE, C_TO_SCM(swig_c_value), SCM_TYPE) 443 %enddef 444 445 %define TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(C_TYPE, SCM_TO_C, C_TO_SCM, SCM_TYPE) 446 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT_WITH_EXPR 447 (C_TYPE, SCM_TO_C(swig_scm_value), C_TO_SCM(swig_c_value), SCM_TYPE) 448 %enddef 449 450 /* We use the macro to define typemaps for some standard types. */ 451 452 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(bool, scm_is_true, scm_from_bool, boolean); 453 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(char, SCM_CHAR, SCM_MAKE_CHAR, char); 454 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned char, SCM_CHAR, SCM_MAKE_CHAR, char); 455 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(int, scm_to_int, scm_from_long, integer); 456 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(short, scm_to_int, scm_from_long, integer); 457 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(long, scm_to_long, scm_from_long, integer); 458 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(ptrdiff_t, scm_to_long, scm_from_long, integer); 459 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned int, scm_to_ulong, scm_from_ulong, integer); 460 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned short, scm_to_ulong, scm_from_ulong, integer); 461 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned long, scm_to_ulong, scm_from_ulong, integer); 462 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(size_t, scm_to_ulong, scm_from_ulong, integer); 463 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(float, scm_to_double, scm_from_double, real); 464 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(double, scm_to_double, scm_from_double, real); 465 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(char *, SWIG_scm2str, SWIG_str02scm, string); 466 TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(const char *, SWIG_scm2str, SWIG_str02scm, string); 467 468 %typemap(freearg) char **PARALLEL_LISTINPUT, char **PARALLEL_VECTORINPUT, 469 const char **PARALLEL_LISTINPUT, const char **PARALLEL_VECTORINPUT 470 { 471 if (($1)!=NULL) { 472 int i; 473 for (i = 0; i<*_global_list_length; i++) 474 if (($1)[i] != NULL) SWIG_free(($1)[i]); 475 SWIG_free($1); 476 } 477 } 478 479 %typemap(freearg) char ***PARALLEL_LISTOUTPUT, char ***PARALLEL_VECTOROUTPUT, 480 const char ***PARALLEL_LISTOUTPUT, const char ***PARALLEL_VECTOROUTPUT 481 { 482 if ((*$1)!=NULL) { 483 int i; 484 for (i = 0; i<_global_arraylentemp; i++) 485 if ((*$1)[i] != NULL) free((*$1)[i]); 486 free(*$1); 487 } 488 } 489