Merge remote-tracking branch 'local-2.0/stable-2.0'
[bpt/guile.git] / libguile / foreign.c
1 /* Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 */
18
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <ffi.h>
24
25 #include <alloca.h>
26 #include <alignof.h>
27 #include <string.h>
28 #include <assert.h>
29
30 #include "libguile/_scm.h"
31 #include "libguile/bytevectors.h"
32 #include "libguile/instructions.h"
33 #include "libguile/threads.h"
34 #include "libguile/foreign.h"
35
36 \f
37
38 SCM_SYMBOL (sym_void, "void");
39 SCM_SYMBOL (sym_float, "float");
40 SCM_SYMBOL (sym_double, "double");
41 SCM_SYMBOL (sym_uint8, "uint8");
42 SCM_SYMBOL (sym_int8, "int8");
43 SCM_SYMBOL (sym_uint16, "uint16");
44 SCM_SYMBOL (sym_int16, "int16");
45 SCM_SYMBOL (sym_uint32, "uint32");
46 SCM_SYMBOL (sym_int32, "int32");
47 SCM_SYMBOL (sym_uint64, "uint64");
48 SCM_SYMBOL (sym_int64, "int64");
49 SCM_SYMBOL (sym_short, "short");
50 SCM_SYMBOL (sym_int, "int");
51 SCM_SYMBOL (sym_long, "long");
52 SCM_SYMBOL (sym_unsigned_short, "unsigned-short");
53 SCM_SYMBOL (sym_unsigned_int, "unsigned-int");
54 SCM_SYMBOL (sym_unsigned_long, "unsigned-long");
55 SCM_SYMBOL (sym_size_t, "size_t");
56
57 /* that's for pointers, you know. */
58 SCM_SYMBOL (sym_asterisk, "*");
59
60 SCM_SYMBOL (sym_null, "%null-pointer");
61 SCM_SYMBOL (sym_null_pointer_error, "null-pointer-error");
62
63 /* The cell representing the null pointer. */
64 static SCM null_pointer;
65
66 #if SIZEOF_VOID_P == 4
67 # define scm_to_uintptr scm_to_uint32
68 # define scm_from_uintptr scm_from_uint32
69 #elif SIZEOF_VOID_P == 8
70 # define scm_to_uintptr scm_to_uint64
71 # define scm_from_uintptr scm_from_uint64
72 #else
73 # error unsupported pointer size
74 #endif
75
76
77 /* Raise a null pointer dereference error. */
78 static void
79 null_pointer_error (const char *func_name)
80 {
81 scm_error (sym_null_pointer_error, func_name,
82 "null pointer dereference", SCM_EOL, SCM_EOL);
83 }
84
85 \f
86 static SCM cif_to_procedure (SCM cif, SCM func_ptr);
87
88
89 static SCM pointer_weak_refs = SCM_BOOL_F;
90
91
92 static void
93 register_weak_reference (SCM from, SCM to)
94 {
95 scm_weak_table_putq_x (pointer_weak_refs, from, to);
96 }
97
98 static void
99 pointer_finalizer_trampoline (GC_PTR ptr, GC_PTR data)
100 {
101 scm_t_pointer_finalizer finalizer = data;
102 finalizer (SCM_POINTER_VALUE (SCM_PACK_POINTER (ptr)));
103 }
104
105 SCM_DEFINE (scm_pointer_p, "pointer?", 1, 0, 0,
106 (SCM obj),
107 "Return @code{#t} if @var{obj} is a pointer object, "
108 "@code{#f} otherwise.\n")
109 #define FUNC_NAME s_scm_pointer_p
110 {
111 return scm_from_bool (SCM_POINTER_P (obj));
112 }
113 #undef FUNC_NAME
114
115 SCM_DEFINE (scm_make_pointer, "make-pointer", 1, 1, 0,
116 (SCM address, SCM finalizer),
117 "Return a foreign pointer object pointing to @var{address}. "
118 "If @var{finalizer} is passed, it should be a pointer to a "
119 "one-argument C function that will be called when the pointer "
120 "object becomes unreachable.")
121 #define FUNC_NAME s_scm_make_pointer
122 {
123 void *c_finalizer;
124 scm_t_uintptr c_address;
125
126 c_address = scm_to_uintptr (address);
127 if (SCM_UNBNDP (finalizer))
128 c_finalizer = NULL;
129 else
130 {
131 SCM_VALIDATE_POINTER (2, finalizer);
132 c_finalizer = SCM_POINTER_VALUE (finalizer);
133 }
134
135 return scm_from_pointer ((void *) c_address, c_finalizer);
136 }
137 #undef FUNC_NAME
138
139 void *
140 scm_to_pointer (SCM pointer)
141 #define FUNC_NAME "scm_to_pointer"
142 {
143 SCM_VALIDATE_POINTER (1, pointer);
144 return SCM_POINTER_VALUE (pointer);
145 }
146 #undef FUNC_NAME
147
148 SCM
149 scm_from_pointer (void *ptr, scm_t_pointer_finalizer finalizer)
150 {
151 SCM ret;
152
153 if (ptr == NULL && finalizer == NULL)
154 ret = null_pointer;
155 else
156 {
157 ret = scm_cell (scm_tc7_pointer, (scm_t_bits) ptr);
158
159 if (finalizer)
160 scm_i_set_finalizer (SCM2PTR (ret), pointer_finalizer_trampoline,
161 finalizer);
162 }
163
164 return ret;
165 }
166
167 SCM_DEFINE (scm_pointer_address, "pointer-address", 1, 0, 0,
168 (SCM pointer),
169 "Return the numerical value of @var{pointer}.")
170 #define FUNC_NAME s_scm_pointer_address
171 {
172 SCM_VALIDATE_POINTER (1, pointer);
173
174 return scm_from_uintptr ((scm_t_uintptr) SCM_POINTER_VALUE (pointer));
175 }
176 #undef FUNC_NAME
177
178 SCM_DEFINE (scm_pointer_to_scm, "pointer->scm", 1, 0, 0,
179 (SCM pointer),
180 "Unsafely cast @var{pointer} to a Scheme object.\n"
181 "Cross your fingers!")
182 #define FUNC_NAME s_scm_pointer_to_scm
183 {
184 SCM_VALIDATE_POINTER (1, pointer);
185
186 return SCM_PACK ((scm_t_bits) SCM_POINTER_VALUE (pointer));
187 }
188 #undef FUNC_NAME
189
190 SCM_DEFINE (scm_scm_to_pointer, "scm->pointer", 1, 0, 0,
191 (SCM scm),
192 "Return a foreign pointer object with the @code{object-address}\n"
193 "of @var{scm}.")
194 #define FUNC_NAME s_scm_scm_to_pointer
195 {
196 SCM ret;
197
198 ret = scm_from_pointer ((void*) SCM_UNPACK (scm), NULL);
199 if (SCM_HEAP_OBJECT_P (ret))
200 register_weak_reference (ret, scm);
201
202 return ret;
203 }
204 #undef FUNC_NAME
205
206 SCM_DEFINE (scm_pointer_to_bytevector, "pointer->bytevector", 2, 2, 0,
207 (SCM pointer, SCM len, SCM offset, SCM uvec_type),
208 "Return a bytevector aliasing the @var{len} bytes pointed\n"
209 "to by @var{pointer}.\n\n"
210 "The user may specify an alternate default interpretation for\n"
211 "the memory by passing the @var{uvec_type} argument, to indicate\n"
212 "that the memory is an array of elements of that type.\n"
213 "@var{uvec_type} should be something that\n"
214 "@code{uniform-vector-element-type} would return, like @code{f32}\n"
215 "or @code{s16}.\n\n"
216 "When @var{offset} is passed, it specifies the offset in bytes\n"
217 "relative to @var{pointer} of the memory region aliased by the\n"
218 "returned bytevector.")
219 #define FUNC_NAME s_scm_pointer_to_bytevector
220 {
221 SCM ret;
222 scm_t_int8 *ptr;
223 size_t boffset, blen;
224 scm_t_array_element_type btype;
225
226 SCM_VALIDATE_POINTER (1, pointer);
227 ptr = SCM_POINTER_VALUE (pointer);
228
229 if (SCM_UNLIKELY (ptr == NULL))
230 null_pointer_error (FUNC_NAME);
231
232 if (SCM_UNBNDP (uvec_type))
233 btype = SCM_ARRAY_ELEMENT_TYPE_VU8;
234 else
235 {
236 int i;
237 for (i = 0; i <= SCM_ARRAY_ELEMENT_TYPE_LAST; i++)
238 if (scm_is_eq (uvec_type, scm_i_array_element_types[i]))
239 break;
240 switch (i)
241 {
242 case SCM_ARRAY_ELEMENT_TYPE_VU8:
243 case SCM_ARRAY_ELEMENT_TYPE_U8:
244 case SCM_ARRAY_ELEMENT_TYPE_S8:
245 case SCM_ARRAY_ELEMENT_TYPE_U16:
246 case SCM_ARRAY_ELEMENT_TYPE_S16:
247 case SCM_ARRAY_ELEMENT_TYPE_U32:
248 case SCM_ARRAY_ELEMENT_TYPE_S32:
249 case SCM_ARRAY_ELEMENT_TYPE_U64:
250 case SCM_ARRAY_ELEMENT_TYPE_S64:
251 case SCM_ARRAY_ELEMENT_TYPE_F32:
252 case SCM_ARRAY_ELEMENT_TYPE_F64:
253 case SCM_ARRAY_ELEMENT_TYPE_C32:
254 case SCM_ARRAY_ELEMENT_TYPE_C64:
255 btype = i;
256 break;
257 default:
258 scm_wrong_type_arg_msg (FUNC_NAME, SCM_ARG1, uvec_type,
259 "uniform vector type");
260 }
261 }
262
263 if (SCM_UNBNDP (offset))
264 boffset = 0;
265 else
266 boffset = scm_to_size_t (offset);
267
268 blen = scm_to_size_t (len);
269
270 ret = scm_c_take_typed_bytevector ((signed char *) ptr + boffset,
271 blen, btype, pointer);
272
273 return ret;
274 }
275 #undef FUNC_NAME
276
277 SCM_DEFINE (scm_bytevector_to_pointer, "bytevector->pointer", 1, 1, 0,
278 (SCM bv, SCM offset),
279 "Return a pointer pointer aliasing the memory pointed to by\n"
280 "@var{bv} or @var{offset} bytes after @var{bv} when @var{offset}\n"
281 "is passed.")
282 #define FUNC_NAME s_scm_bytevector_to_pointer
283 {
284 SCM ret;
285 signed char *ptr;
286 size_t boffset;
287
288 SCM_VALIDATE_BYTEVECTOR (1, bv);
289 ptr = SCM_BYTEVECTOR_CONTENTS (bv);
290
291 if (SCM_UNBNDP (offset))
292 boffset = 0;
293 else
294 boffset = scm_to_unsigned_integer (offset, 0,
295 SCM_BYTEVECTOR_LENGTH (bv) - 1);
296
297 ret = scm_from_pointer (ptr + boffset, NULL);
298 register_weak_reference (ret, bv);
299 return ret;
300 }
301 #undef FUNC_NAME
302
303 SCM_DEFINE (scm_set_pointer_finalizer_x, "set-pointer-finalizer!", 2, 0, 0,
304 (SCM pointer, SCM finalizer),
305 "Arrange for the C procedure wrapped by @var{finalizer} to be\n"
306 "called on the pointer wrapped by @var{pointer} when @var{pointer}\n"
307 "becomes unreachable. Note: the C procedure should not call into\n"
308 "Scheme. If you need a Scheme finalizer, use guardians.")
309 #define FUNC_NAME s_scm_set_pointer_finalizer_x
310 {
311 SCM_VALIDATE_POINTER (1, pointer);
312 SCM_VALIDATE_POINTER (2, finalizer);
313
314 scm_i_add_finalizer (SCM2PTR (pointer), pointer_finalizer_trampoline,
315 SCM_POINTER_VALUE (finalizer));
316
317 return SCM_UNSPECIFIED;
318 }
319 #undef FUNC_NAME
320
321 void
322 scm_i_pointer_print (SCM pointer, SCM port, scm_print_state *pstate)
323 {
324 scm_puts_unlocked ("#<pointer 0x", port);
325 scm_uintprint (scm_to_uintptr (scm_pointer_address (pointer)), 16, port);
326 scm_putc_unlocked ('>', port);
327 }
328
329 \f
330 /* Non-primitive helpers functions. These procedures could be
331 implemented in terms of the primitives above but would be inefficient
332 (heap allocation overhead, Scheme/C round trips, etc.) */
333
334 SCM_DEFINE (scm_dereference_pointer, "dereference-pointer", 1, 0, 0,
335 (SCM pointer),
336 "Assuming @var{pointer} points to a memory region that\n"
337 "holds a pointer, return this pointer.")
338 #define FUNC_NAME s_scm_dereference_pointer
339 {
340 SCM_VALIDATE_POINTER (1, pointer);
341
342 return scm_from_pointer (* (void **) SCM_POINTER_VALUE (pointer), NULL);
343 }
344 #undef FUNC_NAME
345
346 SCM_DEFINE (scm_string_to_pointer, "string->pointer", 1, 1, 0,
347 (SCM string, SCM encoding),
348 "Return a foreign pointer to a nul-terminated copy of\n"
349 "@var{string} in the given @var{encoding}, defaulting to\n"
350 "the current locale encoding. The C string is freed when\n"
351 "the returned foreign pointer becomes unreachable.\n\n"
352 "This is the Scheme equivalent of @code{scm_to_stringn}.")
353 #define FUNC_NAME s_scm_string_to_pointer
354 {
355 SCM_VALIDATE_STRING (1, string);
356
357 /* XXX: Finalizers slow down libgc; they could be avoided if
358 `scm_to_string' & co. were able to use libgc-allocated memory. */
359
360 if (SCM_UNBNDP (encoding))
361 return scm_from_pointer (scm_to_locale_string (string), free);
362 else
363 {
364 char *enc;
365 SCM ret;
366
367 SCM_VALIDATE_STRING (2, encoding);
368
369 enc = scm_to_locale_string (encoding);
370 scm_dynwind_begin (0);
371 scm_dynwind_free (enc);
372
373 ret = scm_from_pointer
374 (scm_to_stringn (string, NULL, enc,
375 scm_i_get_conversion_strategy (SCM_BOOL_F)),
376 free);
377
378 scm_dynwind_end ();
379
380 return ret;
381 }
382 }
383 #undef FUNC_NAME
384
385 SCM_DEFINE (scm_pointer_to_string, "pointer->string", 1, 2, 0,
386 (SCM pointer, SCM length, SCM encoding),
387 "Return the string representing the C string pointed to by\n"
388 "@var{pointer}. If @var{length} is omitted or @code{-1}, the\n"
389 "string is assumed to be nul-terminated. Otherwise\n"
390 "@var{length} is the number of bytes in memory pointed to by\n"
391 "@var{pointer}. The C string is assumed to be in the given\n"
392 "@var{encoding}, defaulting to the current locale encoding.\n\n"
393 "This is the Scheme equivalent of @code{scm_from_stringn}.")
394 #define FUNC_NAME s_scm_pointer_to_string
395 {
396 size_t len;
397
398 SCM_VALIDATE_POINTER (1, pointer);
399
400 if (SCM_UNBNDP (length)
401 || scm_is_true (scm_eqv_p (length, scm_from_int (-1))))
402 len = (size_t)-1;
403 else
404 len = scm_to_size_t (length);
405
406 if (SCM_UNBNDP (encoding))
407 return scm_from_locale_stringn (SCM_POINTER_VALUE (pointer), len);
408 else
409 {
410 char *enc;
411 SCM ret;
412
413 SCM_VALIDATE_STRING (3, encoding);
414
415 enc = scm_to_locale_string (encoding);
416 scm_dynwind_begin (0);
417 scm_dynwind_free (enc);
418
419 ret = scm_from_stringn (SCM_POINTER_VALUE (pointer), len, enc,
420 scm_i_get_conversion_strategy (SCM_BOOL_F));
421
422 scm_dynwind_end ();
423
424 return ret;
425 }
426 }
427 #undef FUNC_NAME
428
429 \f
430
431 SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type),
432 "Return the alignment of @var{type}, in bytes.\n\n"
433 "@var{type} should be a valid C type, like @code{int}.\n"
434 "Alternately @var{type} may be the symbol @code{*}, in which\n"
435 "case the alignment of a pointer is returned. @var{type} may\n"
436 "also be a list of types, in which case the alignment of a\n"
437 "@code{struct} with ABI-conventional packing is returned.")
438 #define FUNC_NAME s_scm_alignof
439 {
440 if (SCM_I_INUMP (type))
441 {
442 switch (SCM_I_INUM (type))
443 {
444 case SCM_FOREIGN_TYPE_FLOAT:
445 return scm_from_size_t (alignof_type (float));
446 case SCM_FOREIGN_TYPE_DOUBLE:
447 return scm_from_size_t (alignof_type (double));
448 case SCM_FOREIGN_TYPE_UINT8:
449 return scm_from_size_t (alignof_type (scm_t_uint8));
450 case SCM_FOREIGN_TYPE_INT8:
451 return scm_from_size_t (alignof_type (scm_t_int8));
452 case SCM_FOREIGN_TYPE_UINT16:
453 return scm_from_size_t (alignof_type (scm_t_uint16));
454 case SCM_FOREIGN_TYPE_INT16:
455 return scm_from_size_t (alignof_type (scm_t_int16));
456 case SCM_FOREIGN_TYPE_UINT32:
457 return scm_from_size_t (alignof_type (scm_t_uint32));
458 case SCM_FOREIGN_TYPE_INT32:
459 return scm_from_size_t (alignof_type (scm_t_int32));
460 case SCM_FOREIGN_TYPE_UINT64:
461 return scm_from_size_t (alignof_type (scm_t_uint64));
462 case SCM_FOREIGN_TYPE_INT64:
463 return scm_from_size_t (alignof_type (scm_t_int64));
464 default:
465 scm_wrong_type_arg (FUNC_NAME, 1, type);
466 }
467 }
468 else if (scm_is_eq (type, sym_asterisk))
469 /* a pointer */
470 return scm_from_size_t (alignof_type (void*));
471 else if (scm_is_pair (type))
472 {
473 /* TYPE is a structure. Section 3-3 of the i386, x86_64, PowerPC,
474 and SPARC P.S. of the System V ABI all say: "Aggregates
475 (structures and arrays) and unions assume the alignment of
476 their most strictly aligned component." */
477 size_t max;
478
479 for (max = 0; scm_is_pair (type); type = SCM_CDR (type))
480 {
481 size_t align;
482
483 align = scm_to_size_t (scm_alignof (SCM_CAR (type)));
484 if (align > max)
485 max = align;
486 }
487
488 return scm_from_size_t (max);
489 }
490 else
491 scm_wrong_type_arg (FUNC_NAME, 1, type);
492 }
493 #undef FUNC_NAME
494
495 SCM_DEFINE (scm_sizeof, "sizeof", 1, 0, 0, (SCM type),
496 "Return the size of @var{type}, in bytes.\n\n"
497 "@var{type} should be a valid C type, like @code{int}.\n"
498 "Alternately @var{type} may be the symbol @code{*}, in which\n"
499 "case the size of a pointer is returned. @var{type} may also\n"
500 "be a list of types, in which case the size of a @code{struct}\n"
501 "with ABI-conventional packing is returned.")
502 #define FUNC_NAME s_scm_sizeof
503 {
504 if (SCM_I_INUMP (type))
505 {
506 switch (SCM_I_INUM (type))
507 {
508 case SCM_FOREIGN_TYPE_FLOAT:
509 return scm_from_size_t (sizeof (float));
510 case SCM_FOREIGN_TYPE_DOUBLE:
511 return scm_from_size_t (sizeof (double));
512 case SCM_FOREIGN_TYPE_UINT8:
513 return scm_from_size_t (sizeof (scm_t_uint8));
514 case SCM_FOREIGN_TYPE_INT8:
515 return scm_from_size_t (sizeof (scm_t_int8));
516 case SCM_FOREIGN_TYPE_UINT16:
517 return scm_from_size_t (sizeof (scm_t_uint16));
518 case SCM_FOREIGN_TYPE_INT16:
519 return scm_from_size_t (sizeof (scm_t_int16));
520 case SCM_FOREIGN_TYPE_UINT32:
521 return scm_from_size_t (sizeof (scm_t_uint32));
522 case SCM_FOREIGN_TYPE_INT32:
523 return scm_from_size_t (sizeof (scm_t_int32));
524 case SCM_FOREIGN_TYPE_UINT64:
525 return scm_from_size_t (sizeof (scm_t_uint64));
526 case SCM_FOREIGN_TYPE_INT64:
527 return scm_from_size_t (sizeof (scm_t_int64));
528 default:
529 scm_wrong_type_arg (FUNC_NAME, 1, type);
530 }
531 }
532 else if (scm_is_eq (type, sym_asterisk))
533 /* a pointer */
534 return scm_from_size_t (sizeof (void*));
535 else if (scm_is_pair (type))
536 {
537 /* a struct */
538 size_t off = 0;
539 while (scm_is_pair (type))
540 {
541 off = ROUND_UP (off, scm_to_size_t (scm_alignof (scm_car (type))));
542 off += scm_to_size_t (scm_sizeof (scm_car (type)));
543 type = scm_cdr (type);
544 }
545 return scm_from_size_t (off);
546 }
547 else
548 scm_wrong_type_arg (FUNC_NAME, 1, type);
549 }
550 #undef FUNC_NAME
551
552
553 /* return 1 on success, 0 on failure */
554 static int
555 parse_ffi_type (SCM type, int return_p, long *n_structs, long *n_struct_elts)
556 {
557 if (SCM_I_INUMP (type))
558 {
559 if ((SCM_I_INUM (type) < 0 )
560 || (SCM_I_INUM (type) > SCM_FOREIGN_TYPE_LAST))
561 return 0;
562 else if (SCM_I_INUM (type) == SCM_FOREIGN_TYPE_VOID && !return_p)
563 return 0;
564 else
565 return 1;
566 }
567 else if (scm_is_eq (type, sym_asterisk))
568 /* a pointer */
569 return 1;
570 else
571 {
572 long len;
573
574 len = scm_ilength (type);
575 if (len < 1)
576 return 0;
577 while (len--)
578 {
579 if (!parse_ffi_type (scm_car (type), 0, n_structs, n_struct_elts))
580 return 0;
581 (*n_struct_elts)++;
582 type = scm_cdr (type);
583 }
584 (*n_structs)++;
585 return 1;
586 }
587 }
588
589 static void
590 fill_ffi_type (SCM type, ffi_type *ftype, ffi_type ***type_ptrs,
591 ffi_type **types)
592 {
593 if (SCM_I_INUMP (type))
594 {
595 switch (SCM_I_INUM (type))
596 {
597 case SCM_FOREIGN_TYPE_FLOAT:
598 *ftype = ffi_type_float;
599 return;
600 case SCM_FOREIGN_TYPE_DOUBLE:
601 *ftype = ffi_type_double;
602 return;
603 case SCM_FOREIGN_TYPE_UINT8:
604 *ftype = ffi_type_uint8;
605 return;
606 case SCM_FOREIGN_TYPE_INT8:
607 *ftype = ffi_type_sint8;
608 return;
609 case SCM_FOREIGN_TYPE_UINT16:
610 *ftype = ffi_type_uint16;
611 return;
612 case SCM_FOREIGN_TYPE_INT16:
613 *ftype = ffi_type_sint16;
614 return;
615 case SCM_FOREIGN_TYPE_UINT32:
616 *ftype = ffi_type_uint32;
617 return;
618 case SCM_FOREIGN_TYPE_INT32:
619 *ftype = ffi_type_sint32;
620 return;
621 case SCM_FOREIGN_TYPE_UINT64:
622 *ftype = ffi_type_uint64;
623 return;
624 case SCM_FOREIGN_TYPE_INT64:
625 *ftype = ffi_type_sint64;
626 return;
627 case SCM_FOREIGN_TYPE_VOID:
628 *ftype = ffi_type_void;
629 return;
630 default:
631 scm_wrong_type_arg_msg ("pointer->procedure", 0, type,
632 "foreign type");
633 }
634 }
635 else if (scm_is_eq (type, sym_asterisk))
636 /* a pointer */
637 {
638 *ftype = ffi_type_pointer;
639 return;
640 }
641 else
642 {
643 long i, len;
644
645 len = scm_ilength (type);
646
647 ftype->size = 0;
648 ftype->alignment = 0;
649 ftype->type = FFI_TYPE_STRUCT;
650 ftype->elements = *type_ptrs;
651 *type_ptrs += len + 1;
652
653 for (i = 0; i < len; i++)
654 {
655 ftype->elements[i] = *types;
656 *types += 1;
657 fill_ffi_type (scm_car (type), ftype->elements[i],
658 type_ptrs, types);
659 type = scm_cdr (type);
660 }
661 ftype->elements[i] = NULL;
662 }
663 }
664
665 /* Return a "cif" (call interface) for the given RETURN_TYPE and
666 ARG_TYPES. */
667 static ffi_cif *
668 make_cif (SCM return_type, SCM arg_types, const char *caller)
669 #define FUNC_NAME caller
670 {
671 SCM walk;
672 long i, nargs, n_structs, n_struct_elts;
673 size_t cif_len;
674 char *mem;
675 ffi_cif *cif;
676 ffi_type **type_ptrs;
677 ffi_type *types;
678
679 nargs = scm_ilength (arg_types);
680 SCM_ASSERT (nargs >= 0, arg_types, 3, FUNC_NAME);
681 /* fixme: assert nargs < 1<<32 */
682 n_structs = n_struct_elts = 0;
683
684 /* For want of talloc, we're going to have to do this in two passes: first we
685 figure out how much memory is needed for all types, then we allocate the
686 cif and the types all in one block. */
687 if (!parse_ffi_type (return_type, 1, &n_structs, &n_struct_elts))
688 scm_wrong_type_arg (FUNC_NAME, 1, return_type);
689 for (walk = arg_types; scm_is_pair (walk); walk = scm_cdr (walk))
690 if (!parse_ffi_type (scm_car (walk), 0, &n_structs, &n_struct_elts))
691 scm_wrong_type_arg (FUNC_NAME, 3, scm_car (walk));
692
693 /* the memory: with space for the cif itself */
694 cif_len = sizeof (ffi_cif);
695
696 /* then ffi_type pointers: one for each arg, one for each struct
697 element, and one for each struct (for null-termination) */
698 cif_len = (ROUND_UP (cif_len, alignof_type (void *))
699 + (nargs + n_structs + n_struct_elts)*sizeof(void*));
700
701 /* then the ffi_type structs themselves, one per arg and struct element, and
702 one for the return val */
703 cif_len = (ROUND_UP (cif_len, alignof_type (ffi_type))
704 + (nargs + n_struct_elts + 1)*sizeof(ffi_type));
705
706 mem = scm_gc_malloc_pointerless (cif_len, "foreign");
707 /* ensure all the memory is initialized, even the holes */
708 memset (mem, 0, cif_len);
709 cif = (ffi_cif *) mem;
710
711 /* reuse cif_len to walk through the mem */
712 cif_len = ROUND_UP (sizeof (ffi_cif), alignof_type (void *));
713 type_ptrs = (ffi_type**)(mem + cif_len);
714 cif_len = ROUND_UP (cif_len
715 + (nargs + n_structs + n_struct_elts)*sizeof(void*),
716 alignof_type (ffi_type));
717 types = (ffi_type*)(mem + cif_len);
718
719 /* whew. now knit the pointers together. */
720 cif->rtype = types++;
721 fill_ffi_type (return_type, cif->rtype, &type_ptrs, &types);
722 cif->arg_types = type_ptrs;
723 type_ptrs += nargs;
724 for (walk = arg_types, i = 0; scm_is_pair (walk); walk = scm_cdr (walk), i++)
725 {
726 cif->arg_types[i] = types++;
727 fill_ffi_type (scm_car (walk), cif->arg_types[i], &type_ptrs, &types);
728 }
729
730 /* round out the cif, and we're done. */
731 cif->abi = FFI_DEFAULT_ABI;
732 cif->nargs = nargs;
733 cif->bytes = 0;
734 cif->flags = 0;
735
736 if (FFI_OK != ffi_prep_cif (cif, FFI_DEFAULT_ABI, cif->nargs, cif->rtype,
737 cif->arg_types))
738 SCM_MISC_ERROR ("ffi_prep_cif failed", SCM_EOL);
739
740 return cif;
741 }
742 #undef FUNC_NAME
743
744 SCM_DEFINE (scm_pointer_to_procedure, "pointer->procedure", 3, 0, 0,
745 (SCM return_type, SCM func_ptr, SCM arg_types),
746 "Make a foreign function.\n\n"
747 "Given the foreign void pointer @var{func_ptr}, its argument and\n"
748 "return types @var{arg_types} and @var{return_type}, return a\n"
749 "procedure that will pass arguments to the foreign function\n"
750 "and return appropriate values.\n\n"
751 "@var{arg_types} should be a list of foreign types.\n"
752 "@code{return_type} should be a foreign type.")
753 #define FUNC_NAME s_scm_pointer_to_procedure
754 {
755 ffi_cif *cif;
756
757 SCM_VALIDATE_POINTER (2, func_ptr);
758
759 cif = make_cif (return_type, arg_types, FUNC_NAME);
760
761 return cif_to_procedure (scm_from_pointer (cif, NULL), func_ptr);
762 }
763 #undef FUNC_NAME
764
765 \f
766
767 /* Pre-generate trampolines for less than 10 arguments. */
768
769 #ifdef WORDS_BIGENDIAN
770 #define OBJCODE_HEADER 0, 0, 0, 8, 0, 0, 0, 40
771 #define META_HEADER 0, 0, 0, 32, 0, 0, 0, 0
772 #else
773 #define OBJCODE_HEADER 8, 0, 0, 0, 40, 0, 0, 0
774 #define META_HEADER 32, 0, 0, 0, 0, 0, 0, 0
775 #endif
776
777 #define CODE(nreq) \
778 OBJCODE_HEADER, \
779 /* 0 */ scm_op_assert_nargs_ee, 0, nreq, /* assert number of args */ \
780 /* 3 */ scm_op_object_ref, 0, /* push the pair with the cif and the function pointer */ \
781 /* 5 */ scm_op_foreign_call, nreq, /* and call (will return value as well) */ \
782 /* 7 */ scm_op_nop, \
783 /* 8 */ META (3, 7, nreq)
784
785 #define META(start, end, nreq) \
786 META_HEADER, \
787 /* 0 */ scm_op_make_eol, /* bindings */ \
788 /* 1 */ scm_op_make_eol, /* sources */ \
789 /* 2 */ scm_op_make_int8, start, scm_op_make_int8, end, /* arity: from ip N to ip N */ \
790 /* 6 */ scm_op_make_int8, nreq, /* the arity is N required args */ \
791 /* 8 */ scm_op_list, 0, 3, /* make a list of those 3 vals */ \
792 /* 11 */ scm_op_list, 0, 1, /* and the arities will be a list of that one list */ \
793 /* 14 */ scm_op_load_symbol, 0, 0, 4, 'n', 'a', 'm', 'e', /* `name' */ \
794 /* 22 */ scm_op_object_ref, 1, /* the name from the object table */ \
795 /* 24 */ scm_op_cons, /* make a pair for the properties */ \
796 /* 25 */ scm_op_list, 0, 4, /* pack bindings, sources, and arities into list */ \
797 /* 28 */ scm_op_return, /* and return */ \
798 /* 29 */ scm_op_nop, scm_op_nop, scm_op_nop \
799 /* 32 */
800
801 static const struct
802 {
803 scm_t_uint64 dummy; /* ensure 8-byte alignment; perhaps there's a better way */
804 const scm_t_uint8 bytes[10 * (sizeof (struct scm_objcode) + 8
805 + sizeof (struct scm_objcode) + 32)];
806 } raw_bytecode = {
807 0,
808 {
809 CODE (0), CODE (1), CODE (2), CODE (3), CODE (4),
810 CODE (5), CODE (6), CODE (7), CODE (8), CODE (9)
811 }
812 };
813
814 #undef CODE
815 #undef META
816 #undef OBJCODE_HEADER
817 #undef META_HEADER
818
819 /*
820 (defun generate-objcode-cells (n)
821 "Generate objcode cells for up to N arguments"
822 (interactive "p")
823 (let ((i 0))
824 (while (< i n)
825 (insert
826 (format " { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + %d) },\n"
827 (* (+ 4 4 8 4 4 32) i)))
828 (insert " { SCM_BOOL_F, SCM_PACK (0) },\n")
829 (setq i (1+ i)))))
830 */
831 #define STATIC_OBJCODE_TAG \
832 SCM_PACK (SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_STATIC, 0))
833
834 static const struct
835 {
836 scm_t_uint64 dummy; /* alignment */
837 scm_t_cell cells[10 * 2]; /* 10 double cells */
838 } objcode_cells = {
839 0,
840 /* C-u 1 0 M-x generate-objcode-cells RET */
841 {
842 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 0) },
843 { SCM_BOOL_F, SCM_PACK (0) },
844 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 56) },
845 { SCM_BOOL_F, SCM_PACK (0) },
846 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 112) },
847 { SCM_BOOL_F, SCM_PACK (0) },
848 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 168) },
849 { SCM_BOOL_F, SCM_PACK (0) },
850 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 224) },
851 { SCM_BOOL_F, SCM_PACK (0) },
852 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 280) },
853 { SCM_BOOL_F, SCM_PACK (0) },
854 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 336) },
855 { SCM_BOOL_F, SCM_PACK (0) },
856 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 392) },
857 { SCM_BOOL_F, SCM_PACK (0) },
858 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 448) },
859 { SCM_BOOL_F, SCM_PACK (0) },
860 { STATIC_OBJCODE_TAG, SCM_PACK (raw_bytecode.bytes + 504) },
861 { SCM_BOOL_F, SCM_PACK (0) }
862 }
863 };
864
865 static const SCM objcode_trampolines[10] = {
866 SCM_PACK (objcode_cells.cells+0),
867 SCM_PACK (objcode_cells.cells+2),
868 SCM_PACK (objcode_cells.cells+4),
869 SCM_PACK (objcode_cells.cells+6),
870 SCM_PACK (objcode_cells.cells+8),
871 SCM_PACK (objcode_cells.cells+10),
872 SCM_PACK (objcode_cells.cells+12),
873 SCM_PACK (objcode_cells.cells+14),
874 SCM_PACK (objcode_cells.cells+16),
875 SCM_PACK (objcode_cells.cells+18),
876 };
877
878 static SCM
879 cif_to_procedure (SCM cif, SCM func_ptr)
880 {
881 ffi_cif *c_cif;
882 unsigned int nargs;
883 SCM objcode, table, ret;
884
885 c_cif = (ffi_cif *) SCM_POINTER_VALUE (cif);
886 nargs = c_cif->nargs;
887
888 if (nargs < 10)
889 objcode = objcode_trampolines[nargs];
890 else
891 scm_misc_error ("make-foreign-function", "args >= 10 currently unimplemented",
892 SCM_EOL);
893
894 table = scm_c_make_vector (2, SCM_UNDEFINED);
895 SCM_SIMPLE_VECTOR_SET (table, 0, scm_cons (cif, func_ptr));
896 SCM_SIMPLE_VECTOR_SET (table, 1, SCM_BOOL_F); /* name */
897 ret = scm_make_program (objcode, table, SCM_BOOL_F);
898
899 return ret;
900 }
901
902 /* Set *LOC to the foreign representation of X with TYPE. */
903 static void
904 unpack (const ffi_type *type, void *loc, SCM x, int return_value_p)
905 #define FUNC_NAME "scm_i_foreign_call"
906 {
907 switch (type->type)
908 {
909 case FFI_TYPE_FLOAT:
910 *(float *) loc = scm_to_double (x);
911 break;
912 case FFI_TYPE_DOUBLE:
913 *(double *) loc = scm_to_double (x);
914 break;
915
916 /* For integer return values smaller than `int', libffi expects the
917 result in an `ffi_arg'-long buffer. */
918
919 case FFI_TYPE_UINT8:
920 if (return_value_p)
921 *(ffi_arg *) loc = scm_to_uint8 (x);
922 else
923 *(scm_t_uint8 *) loc = scm_to_uint8 (x);
924 break;
925 case FFI_TYPE_SINT8:
926 if (return_value_p)
927 *(ffi_arg *) loc = scm_to_int8 (x);
928 else
929 *(scm_t_int8 *) loc = scm_to_int8 (x);
930 break;
931 case FFI_TYPE_UINT16:
932 if (return_value_p)
933 *(ffi_arg *) loc = scm_to_uint16 (x);
934 else
935 *(scm_t_uint16 *) loc = scm_to_uint16 (x);
936 break;
937 case FFI_TYPE_SINT16:
938 if (return_value_p)
939 *(ffi_arg *) loc = scm_to_int16 (x);
940 else
941 *(scm_t_int16 *) loc = scm_to_int16 (x);
942 break;
943 case FFI_TYPE_UINT32:
944 if (return_value_p)
945 *(ffi_arg *) loc = scm_to_uint32 (x);
946 else
947 *(scm_t_uint32 *) loc = scm_to_uint32 (x);
948 break;
949 case FFI_TYPE_SINT32:
950 if (return_value_p)
951 *(ffi_arg *) loc = scm_to_int32 (x);
952 else
953 *(scm_t_int32 *) loc = scm_to_int32 (x);
954 break;
955 case FFI_TYPE_UINT64:
956 *(scm_t_uint64 *) loc = scm_to_uint64 (x);
957 break;
958 case FFI_TYPE_SINT64:
959 *(scm_t_int64 *) loc = scm_to_int64 (x);
960 break;
961 case FFI_TYPE_STRUCT:
962 SCM_VALIDATE_POINTER (1, x);
963 memcpy (loc, SCM_POINTER_VALUE (x), type->size);
964 break;
965 case FFI_TYPE_POINTER:
966 SCM_VALIDATE_POINTER (1, x);
967 *(void **) loc = SCM_POINTER_VALUE (x);
968 break;
969 case FFI_TYPE_VOID:
970 /* Do nothing. */
971 break;
972 default:
973 abort ();
974 }
975 }
976 #undef FUNC_NAME
977
978 /* Return a Scheme representation of the foreign value at LOC of type
979 TYPE. When RETURN_VALUE_P is true, LOC is assumed to point to a
980 return value buffer; otherwise LOC is assumed to point to an
981 argument buffer. */
982 static SCM
983 pack (const ffi_type * type, const void *loc, int return_value_p)
984 {
985 switch (type->type)
986 {
987 case FFI_TYPE_VOID:
988 return SCM_UNSPECIFIED;
989 case FFI_TYPE_FLOAT:
990 return scm_from_double (*(float *) loc);
991 case FFI_TYPE_DOUBLE:
992 return scm_from_double (*(double *) loc);
993
994 /* For integer return values smaller than `int', libffi stores the
995 result in an `ffi_arg'-long buffer, of which only the
996 significant bits must be kept---hence the pair of casts below.
997 See <http://thread.gmane.org/gmane.comp.lib.ffi.general/406>
998 for details. */
999
1000 case FFI_TYPE_UINT8:
1001 if (return_value_p)
1002 return scm_from_uint8 ((scm_t_uint8) *(ffi_arg *) loc);
1003 else
1004 return scm_from_uint8 (* (scm_t_uint8 *) loc);
1005 case FFI_TYPE_SINT8:
1006 if (return_value_p)
1007 return scm_from_int8 ((scm_t_int8) *(ffi_arg *) loc);
1008 else
1009 return scm_from_int8 (* (scm_t_int8 *) loc);
1010 case FFI_TYPE_UINT16:
1011 if (return_value_p)
1012 return scm_from_uint16 ((scm_t_uint16) *(ffi_arg *) loc);
1013 else
1014 return scm_from_uint16 (* (scm_t_uint16 *) loc);
1015 case FFI_TYPE_SINT16:
1016 if (return_value_p)
1017 return scm_from_int16 ((scm_t_int16) *(ffi_arg *) loc);
1018 else
1019 return scm_from_int16 (* (scm_t_int16 *) loc);
1020 case FFI_TYPE_UINT32:
1021 if (return_value_p)
1022 return scm_from_uint32 ((scm_t_uint32) *(ffi_arg *) loc);
1023 else
1024 return scm_from_uint32 (* (scm_t_uint32 *) loc);
1025 case FFI_TYPE_SINT32:
1026 if (return_value_p)
1027 return scm_from_int32 ((scm_t_int32) *(ffi_arg *) loc);
1028 else
1029 return scm_from_int32 (* (scm_t_int32 *) loc);
1030 case FFI_TYPE_UINT64:
1031 return scm_from_uint64 (*(scm_t_uint64 *) loc);
1032 case FFI_TYPE_SINT64:
1033 return scm_from_int64 (*(scm_t_int64 *) loc);
1034
1035 case FFI_TYPE_STRUCT:
1036 {
1037 void *mem = scm_gc_malloc_pointerless (type->size, "foreign");
1038 memcpy (mem, loc, type->size);
1039 return scm_from_pointer (mem, NULL);
1040 }
1041 case FFI_TYPE_POINTER:
1042 return scm_from_pointer (*(void **) loc, NULL);
1043 default:
1044 abort ();
1045 }
1046 }
1047
1048
1049 SCM
1050 scm_i_foreign_call (SCM foreign, const SCM *argv)
1051 {
1052 /* FOREIGN is the pair that cif_to_procedure set as the 0th element of the
1053 objtable. */
1054 ffi_cif *cif;
1055 void (*func) (void);
1056 scm_t_uint8 *data;
1057 void *rvalue;
1058 void **args;
1059 unsigned i;
1060 size_t arg_size;
1061 scm_t_ptrdiff off;
1062
1063 cif = SCM_POINTER_VALUE (SCM_CAR (foreign));
1064 func = SCM_POINTER_VALUE (SCM_CDR (foreign));
1065
1066 /* Argument pointers. */
1067 args = alloca (sizeof (void *) * cif->nargs);
1068
1069 /* Compute the worst-case amount of memory needed to store all the argument
1070 values. Note: as of libffi 3.0.9 `cif->bytes' is undocumented and is zero,
1071 so it can't be used for that purpose. */
1072 for (i = 0, arg_size = 0; i < cif->nargs; i++)
1073 arg_size += cif->arg_types[i]->size + cif->arg_types[i]->alignment - 1;
1074
1075 /* Space for argument values, followed by return value. */
1076 data = alloca (arg_size + cif->rtype->size
1077 + max (sizeof (void *), cif->rtype->alignment));
1078
1079 /* Unpack ARGV to native values, setting ARGV pointers. */
1080 for (i = 0, off = 0;
1081 i < cif->nargs;
1082 off = (scm_t_uint8 *) args[i] - data + cif->arg_types[i]->size,
1083 i++)
1084 {
1085 /* Suitably align the storage area for argument I. */
1086 args[i] = (void *) ROUND_UP ((scm_t_uintptr) data + off,
1087 cif->arg_types[i]->alignment);
1088 assert ((scm_t_uintptr) args[i] % cif->arg_types[i]->alignment == 0);
1089 unpack (cif->arg_types[i], args[i], argv[i], 0);
1090 }
1091
1092 /* Prepare space for the return value. On some platforms, such as
1093 `armv5tel-*-linux-gnueabi', the return value has to be at least
1094 word-aligned, even if its type doesn't have any alignment requirement as is
1095 the case with `char'. */
1096 rvalue = (void *) ROUND_UP ((scm_t_uintptr) data + off,
1097 max (sizeof (void *), cif->rtype->alignment));
1098
1099 /* off we go! */
1100 ffi_call (cif, func, rvalue, args);
1101
1102 return pack (cif->rtype, rvalue, 1);
1103 }
1104
1105 \f
1106 /* Function pointers aka. "callbacks" or "closures". */
1107
1108 #ifdef FFI_CLOSURES
1109
1110 /* Trampoline to invoke a libffi closure that wraps a Scheme
1111 procedure. */
1112 static void
1113 invoke_closure (ffi_cif *cif, void *ret, void **args, void *data)
1114 {
1115 size_t i;
1116 SCM proc, *argv, result;
1117
1118 proc = SCM_PACK_POINTER (data);
1119
1120 argv = alloca (cif->nargs * sizeof (*argv));
1121
1122 /* Pack ARGS to SCM values, setting ARGV pointers. */
1123 for (i = 0; i < cif->nargs; i++)
1124 argv[i] = pack (cif->arg_types[i], args[i], 0);
1125
1126 result = scm_call_n (proc, argv, cif->nargs);
1127
1128 unpack (cif->rtype, ret, result, 1);
1129 }
1130
1131 SCM_DEFINE (scm_procedure_to_pointer, "procedure->pointer", 3, 0, 0,
1132 (SCM return_type, SCM proc, SCM arg_types),
1133 "Return a pointer to a C function of type @var{return_type}\n"
1134 "taking arguments of types @var{arg_types} (a list) and\n"
1135 "behaving as a proxy to procedure @var{proc}. Thus\n"
1136 "@var{proc}'s arity, supported argument types, and return\n"
1137 "type should match @var{return_type} and @var{arg_types}.\n")
1138 #define FUNC_NAME s_scm_procedure_to_pointer
1139 {
1140 SCM cif_pointer, pointer;
1141 ffi_cif *cif;
1142 ffi_status err;
1143 void *closure, *executable;
1144
1145 cif = make_cif (return_type, arg_types, FUNC_NAME);
1146
1147 closure = ffi_closure_alloc (sizeof (ffi_closure), &executable);
1148 err = ffi_prep_closure_loc ((ffi_closure *) closure, cif,
1149 invoke_closure, SCM_UNPACK_POINTER (proc),
1150 executable);
1151 if (err != FFI_OK)
1152 {
1153 ffi_closure_free (closure);
1154 SCM_MISC_ERROR ("`ffi_prep_closure_loc' failed", SCM_EOL);
1155 }
1156
1157 /* CIF points to GC-managed memory and it should remain as long as
1158 POINTER (see below) is live. Wrap it in a Scheme pointer to then
1159 hold a weak reference on it. */
1160 cif_pointer = scm_from_pointer (cif, NULL);
1161
1162 if (closure == executable)
1163 {
1164 pointer = scm_from_pointer (executable, ffi_closure_free);
1165 register_weak_reference (pointer,
1166 scm_list_2 (proc, cif_pointer));
1167 }
1168 else
1169 {
1170 /* CLOSURE needs to be freed eventually. However, since
1171 `GC_all_interior_pointers' is disabled, we can't just register
1172 a finalizer for CLOSURE. Instead, we create a pointer object
1173 for CLOSURE, with a finalizer, and register it as a weak
1174 reference of POINTER. */
1175 SCM friend;
1176
1177 pointer = scm_from_pointer (executable, NULL);
1178 friend = scm_from_pointer (closure, ffi_closure_free);
1179
1180 register_weak_reference (pointer,
1181 scm_list_3 (proc, cif_pointer, friend));
1182 }
1183
1184 return pointer;
1185 }
1186 #undef FUNC_NAME
1187
1188 #endif /* FFI_CLOSURES */
1189
1190 \f
1191
1192 static void
1193 scm_init_foreign (void)
1194 {
1195 #ifndef SCM_MAGIC_SNARFER
1196 #include "libguile/foreign.x"
1197 #endif
1198 scm_define (sym_void, scm_from_uint8 (SCM_FOREIGN_TYPE_VOID));
1199 scm_define (sym_float, scm_from_uint8 (SCM_FOREIGN_TYPE_FLOAT));
1200 scm_define (sym_double, scm_from_uint8 (SCM_FOREIGN_TYPE_DOUBLE));
1201 scm_define (sym_uint8, scm_from_uint8 (SCM_FOREIGN_TYPE_UINT8));
1202 scm_define (sym_int8, scm_from_uint8 (SCM_FOREIGN_TYPE_INT8));
1203 scm_define (sym_uint16, scm_from_uint8 (SCM_FOREIGN_TYPE_UINT16));
1204 scm_define (sym_int16, scm_from_uint8 (SCM_FOREIGN_TYPE_INT16));
1205 scm_define (sym_uint32, scm_from_uint8 (SCM_FOREIGN_TYPE_UINT32));
1206 scm_define (sym_int32, scm_from_uint8 (SCM_FOREIGN_TYPE_INT32));
1207 scm_define (sym_uint64, scm_from_uint8 (SCM_FOREIGN_TYPE_UINT64));
1208 scm_define (sym_int64, scm_from_uint8 (SCM_FOREIGN_TYPE_INT64));
1209
1210 scm_define (sym_short,
1211 #if SIZEOF_SHORT == 8
1212 scm_from_uint8 (SCM_FOREIGN_TYPE_INT64)
1213 #elif SIZEOF_SHORT == 4
1214 scm_from_uint8 (SCM_FOREIGN_TYPE_INT32)
1215 #elif SIZEOF_SHORT == 2
1216 scm_from_uint8 (SCM_FOREIGN_TYPE_INT16)
1217 #else
1218 # error unsupported sizeof (short)
1219 #endif
1220 );
1221
1222 scm_define (sym_unsigned_short,
1223 #if SIZEOF_SHORT == 8
1224 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT64)
1225 #elif SIZEOF_SHORT == 4
1226 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT32)
1227 #elif SIZEOF_SHORT == 2
1228 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT16)
1229 #else
1230 # error unsupported sizeof (short)
1231 #endif
1232 );
1233
1234 scm_define (sym_int,
1235 #if SIZEOF_INT == 8
1236 scm_from_uint8 (SCM_FOREIGN_TYPE_INT64)
1237 #elif SIZEOF_INT == 4
1238 scm_from_uint8 (SCM_FOREIGN_TYPE_INT32)
1239 #else
1240 # error unsupported sizeof (int)
1241 #endif
1242 );
1243
1244 scm_define (sym_unsigned_int,
1245 #if SIZEOF_UNSIGNED_INT == 8
1246 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT64)
1247 #elif SIZEOF_UNSIGNED_INT == 4
1248 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT32)
1249 #else
1250 # error unsupported sizeof (unsigned int)
1251 #endif
1252 );
1253
1254 scm_define (sym_long,
1255 #if SIZEOF_LONG == 8
1256 scm_from_uint8 (SCM_FOREIGN_TYPE_INT64)
1257 #elif SIZEOF_LONG == 4
1258 scm_from_uint8 (SCM_FOREIGN_TYPE_INT32)
1259 #else
1260 # error unsupported sizeof (long)
1261 #endif
1262 );
1263
1264 scm_define (sym_unsigned_long,
1265 #if SIZEOF_UNSIGNED_LONG == 8
1266 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT64)
1267 #elif SIZEOF_UNSIGNED_LONG == 4
1268 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT32)
1269 #else
1270 # error unsupported sizeof (unsigned long)
1271 #endif
1272 );
1273
1274 scm_define (sym_size_t,
1275 #if SIZEOF_SIZE_T == 8
1276 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT64)
1277 #elif SIZEOF_SIZE_T == 4
1278 scm_from_uint8 (SCM_FOREIGN_TYPE_UINT32)
1279 #else
1280 # error unsupported sizeof (size_t)
1281 #endif
1282 );
1283
1284 null_pointer = scm_cell (scm_tc7_pointer, 0);
1285 scm_define (sym_null, null_pointer);
1286 }
1287
1288 void
1289 scm_register_foreign (void)
1290 {
1291 scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
1292 "scm_init_foreign",
1293 (scm_t_extension_init_func)scm_init_foreign,
1294 NULL);
1295 pointer_weak_refs = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
1296 }
1297
1298 /*
1299 Local Variables:
1300 c-file-style: "gnu"
1301 End:
1302 */