PageRenderTime 28ms CodeModel.GetById 17ms app.highlight 6ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/Lib/guile/list-vector.i

#
Swig | 488 lines | 315 code | 65 blank | 108 comment | 0 complexity | ae0a59257f6e85610d568d45139c5edc MD5 | raw file
  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 = gh_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 = gh_vector_ref($input, gh_int2scm(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 = gh_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 = gh_cdr(rest)) {
 89	   SCM swig_scm_value = gh_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 = gh_make_vector(gh_int2scm(*$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	 gh_vector_set_x(res, gh_int2scm(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 = gh_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
203TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(bool, gh_scm2bool, gh_bool2scm, boolean);
204TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(char, gh_scm2char, gh_char2scm, char);
205TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned char, gh_scm2char, gh_char2scm, char);
206TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(int, gh_scm2int, gh_int2scm, integer);
207TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(short, gh_scm2int, gh_int2scm, integer);
208TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(long, gh_scm2long, gh_long2scm, integer);
209TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(ptrdiff_t, gh_scm2long, gh_long2scm, integer);
210TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned int, gh_scm2ulong, gh_ulong2scm, integer);
211TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned short, gh_scm2ulong, gh_ulong2scm, integer);
212TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(unsigned long, gh_scm2ulong, gh_ulong2scm, integer);
213TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(size_t, gh_scm2ulong, gh_ulong2scm, integer);
214TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(float, gh_scm2double, gh_double2scm, real);
215TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(double, gh_scm2double, gh_double2scm, real);
216TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(char *, SWIG_scm2str, gh_str02scm, string);
217TYPEMAP_LIST_VECTOR_INPUT_OUTPUT(const char *, SWIG_scm2str, gh_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 = gh_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 = gh_vector_ref($input, gh_int2scm(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 = gh_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 = gh_cdr(rest)) {
342	   SCM swig_scm_value = gh_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 = gh_make_vector(gh_int2scm(_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	 gh_vector_set_x(res, gh_int2scm(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 = gh_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
452TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(bool, gh_scm2bool, gh_bool2scm, boolean);
453TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(char, gh_scm2char, gh_char2scm, char);
454TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned char, gh_scm2char, gh_char2scm, char);
455TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(int, gh_scm2int, gh_int2scm, integer);
456TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(short, gh_scm2int, gh_int2scm, integer);
457TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(long, gh_scm2long, gh_long2scm, integer);
458TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(ptrdiff_t, gh_scm2long, gh_long2scm, integer);
459TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned int, gh_scm2ulong, gh_ulong2scm, integer);
460TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned short, gh_scm2ulong, gh_ulong2scm, integer);
461TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(unsigned long, gh_scm2ulong, gh_ulong2scm, integer);
462TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(size_t, gh_scm2ulong, gh_ulong2scm, integer);
463TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(float, gh_scm2double, gh_double2scm, real);
464TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(double, gh_scm2double, gh_double2scm, real);
465TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(char *, SWIG_scm2str, gh_str02scm, string);
466TYPEMAP_PARALLEL_LIST_VECTOR_INPUT_OUTPUT(const char *, SWIG_scm2str, gh_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}