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