1 /* Copyright (C) 2010 Free Software Foundation, Inc.
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.
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.
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
30 sizeof_type (scm_t_foreign_type type
)
34 case SCM_FOREIGN_TYPE_VOID
: abort ();
35 case SCM_FOREIGN_TYPE_FLOAT
: return sizeof(float);
36 case SCM_FOREIGN_TYPE_DOUBLE
: return sizeof(double);
37 case SCM_FOREIGN_TYPE_UINT8
: return sizeof(scm_t_uint8
);
38 case SCM_FOREIGN_TYPE_INT8
: return sizeof(scm_t_int8
);
39 case SCM_FOREIGN_TYPE_UINT16
: return sizeof(scm_t_uint16
);
40 case SCM_FOREIGN_TYPE_INT16
: return sizeof(scm_t_int16
);
41 case SCM_FOREIGN_TYPE_UINT32
: return sizeof(scm_t_uint32
);
42 case SCM_FOREIGN_TYPE_INT32
: return sizeof(scm_t_int32
);
43 case SCM_FOREIGN_TYPE_UINT64
: return sizeof(scm_t_uint64
);
44 case SCM_FOREIGN_TYPE_INT64
: return sizeof(scm_t_int64
);
45 case SCM_FOREIGN_TYPE_STRUCT
: abort ();
46 case SCM_FOREIGN_TYPE_POINTER
: return sizeof(void*);
53 foreign_finalizer_trampoline (GC_PTR ptr
, GC_PTR data
)
55 scm_t_foreign_finalizer finalizer
= data
;
56 finalizer (SCM_FOREIGN_OBJECT (PTR2SCM (ptr
), void*));
60 scm_c_from_foreign (scm_t_foreign_type type
, void *val
, size_t size
,
61 scm_t_foreign_finalizer finalizer
)
65 size
= sizeof_type (type
);
67 ret
= scm_gc_malloc_pointerless (sizeof (scm_t_bits
) * 2 + size
, "foreign");
68 SCM_SET_CELL_WORD_0 (PTR2SCM (ret
), scm_tc7_foreign
| (type
<<8));
70 /* set SCM_FOREIGN_OBJECT to point to the third word of the object, which will
71 be 8-byte aligned. Then copy *val into that space. */
72 SCM_SET_CELL_WORD_1 (PTR2SCM (ret
),
73 (scm_t_bits
)SCM_CELL_OBJECT_LOC (PTR2SCM (ret
), 2));
74 memcpy (SCM_FOREIGN_OBJECT (PTR2SCM (ret
), void), val
, size
);
78 /* Register a finalizer for the newly created instance. */
79 GC_finalization_proc prev_finalizer
;
80 GC_PTR prev_finalizer_data
;
81 GC_REGISTER_FINALIZER_NO_ORDER (ret
,
82 foreign_finalizer_trampoline
,
85 &prev_finalizer_data
);
92 scm_c_take_foreign (scm_t_foreign_type type
, void *val
,
93 scm_t_foreign_finalizer finalizer
)
97 ret
= scm_gc_malloc_pointerless (sizeof (scm_t_bits
) * 2, "foreign");
98 SCM_SET_CELL_WORD_0 (PTR2SCM (ret
), scm_tc7_foreign
| (type
<<8));
99 /* Set SCM_FOREIGN_OBJECT to the given pointer. */
100 SCM_SET_CELL_WORD_1 (PTR2SCM (ret
), (scm_t_bits
)val
);
104 /* Register a finalizer for the newly created instance. */
105 GC_finalization_proc prev_finalizer
;
106 GC_PTR prev_finalizer_data
;
107 GC_REGISTER_FINALIZER_NO_ORDER (ret
,
108 foreign_finalizer_trampoline
,
111 &prev_finalizer_data
);
114 return PTR2SCM (ret
);
117 SCM_DEFINE (scm_foreign_ref
, "foreign-ref", 1, 0, 0,
119 "Reference the foreign value wrapped by @var{foreign}.\n\n"
120 "Note that only \"simple\" types may be referenced by this\n"
121 "function. See @code{foreign-struct-ref} or @code{foreign-pointer-ref}\n"
122 "for structs or pointers, respectively.")
123 #define FUNC_NAME s_scm_foreign_ref
125 SCM_VALIDATE_FOREIGN_SIMPLE (1, foreign
);
127 switch (SCM_FOREIGN_TYPE (foreign
))
129 case SCM_FOREIGN_TYPE_FLOAT
:
130 return scm_from_double (SCM_FOREIGN_OBJECT_REF (foreign
, float));
131 case SCM_FOREIGN_TYPE_DOUBLE
:
132 return scm_from_double (SCM_FOREIGN_OBJECT_REF (foreign
, double));
133 case SCM_FOREIGN_TYPE_UINT8
:
134 return scm_from_uint8 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_uint8
));
135 case SCM_FOREIGN_TYPE_INT8
:
136 return scm_from_int8 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_int8
));
137 case SCM_FOREIGN_TYPE_UINT16
:
138 return scm_from_uint16 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_uint16
));
139 case SCM_FOREIGN_TYPE_INT16
:
140 return scm_from_int16 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_int16
));
141 case SCM_FOREIGN_TYPE_UINT32
:
142 return scm_from_uint32 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_uint32
));
143 case SCM_FOREIGN_TYPE_INT32
:
144 return scm_from_int32 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_int32
));
145 case SCM_FOREIGN_TYPE_UINT64
:
146 return scm_from_uint64 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_uint64
));
147 case SCM_FOREIGN_TYPE_INT64
:
148 return scm_from_int64 (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_int64
));
149 case SCM_FOREIGN_TYPE_VOID
:
150 case SCM_FOREIGN_TYPE_STRUCT
:
151 case SCM_FOREIGN_TYPE_POINTER
:
153 /* other cases should have been caught by the FOREIGN_SIMPLE check */
159 SCM_DEFINE (scm_foreign_set_x
, "foreign-set!", 2, 0, 0,
160 (SCM foreign
, SCM val
),
161 "Set the foreign value wrapped by @var{foreign}.\n\n"
162 "Note that only \"simple\" types may be set by this function.\n"
163 "See @code{foreign-struct-ref} or @code{foreign-pointer-ref} for\n"
164 "structs or pointers, respectively.")
165 #define FUNC_NAME s_scm_foreign_set_x
167 SCM_VALIDATE_FOREIGN_SIMPLE (1, foreign
);
169 switch (SCM_FOREIGN_TYPE (foreign
))
171 case SCM_FOREIGN_TYPE_FLOAT
:
172 SCM_FOREIGN_OBJECT_SET (foreign
, float, scm_to_double (val
));
174 case SCM_FOREIGN_TYPE_DOUBLE
:
175 SCM_FOREIGN_OBJECT_SET (foreign
, double, scm_to_double (val
));
177 case SCM_FOREIGN_TYPE_UINT8
:
178 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_uint8
, scm_to_uint8 (val
));
180 case SCM_FOREIGN_TYPE_INT8
:
181 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_int8
, scm_to_int8 (val
));
183 case SCM_FOREIGN_TYPE_UINT16
:
184 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_uint16
, scm_to_uint16 (val
));
186 case SCM_FOREIGN_TYPE_INT16
:
187 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_int16
, scm_to_int16 (val
));
189 case SCM_FOREIGN_TYPE_UINT32
:
190 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_uint32
, scm_to_uint32 (val
));
192 case SCM_FOREIGN_TYPE_INT32
:
193 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_int32
, scm_to_int32 (val
));
195 case SCM_FOREIGN_TYPE_UINT64
:
196 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_uint64
, scm_to_uint64 (val
));
198 case SCM_FOREIGN_TYPE_INT64
:
199 SCM_FOREIGN_OBJECT_SET (foreign
, scm_t_int64
, scm_to_int64 (val
));
201 case SCM_FOREIGN_TYPE_VOID
:
202 case SCM_FOREIGN_TYPE_STRUCT
:
203 case SCM_FOREIGN_TYPE_POINTER
:
205 /* other cases should have been caught by the FOREIGN_SIMPLE check */
208 return SCM_UNSPECIFIED
;
213 scm_i_foreign_print (SCM foreign
, SCM port
, scm_print_state
*pstate
)
215 scm_puts ("#<foreign ", port
);
216 switch (SCM_FOREIGN_TYPE (foreign
))
218 case SCM_FOREIGN_TYPE_VOID
:
220 case SCM_FOREIGN_TYPE_FLOAT
:
221 scm_puts ("float ", port
);
222 scm_display (scm_foreign_ref (foreign
), port
);
224 case SCM_FOREIGN_TYPE_DOUBLE
:
225 scm_puts ("double ", port
);
226 scm_display (scm_foreign_ref (foreign
), port
);
228 case SCM_FOREIGN_TYPE_UINT8
:
229 scm_puts ("uint8 ", port
);
230 scm_display (scm_foreign_ref (foreign
), port
);
232 case SCM_FOREIGN_TYPE_INT8
:
233 scm_puts ("int8 ", port
);
234 scm_display (scm_foreign_ref (foreign
), port
);
236 case SCM_FOREIGN_TYPE_UINT16
:
237 scm_puts ("uint16 ", port
);
238 scm_display (scm_foreign_ref (foreign
), port
);
240 case SCM_FOREIGN_TYPE_INT16
:
241 scm_puts ("int16 ", port
);
242 scm_display (scm_foreign_ref (foreign
), port
);
244 case SCM_FOREIGN_TYPE_UINT32
:
245 scm_puts ("uint32 ", port
);
246 scm_display (scm_foreign_ref (foreign
), port
);
248 case SCM_FOREIGN_TYPE_INT32
:
249 scm_puts ("int32 ", port
);
250 scm_display (scm_foreign_ref (foreign
), port
);
252 case SCM_FOREIGN_TYPE_UINT64
:
253 scm_puts ("uint64 ", port
);
254 scm_display (scm_foreign_ref (foreign
), port
);
256 case SCM_FOREIGN_TYPE_INT64
:
257 scm_puts ("int64 ", port
);
258 scm_display (scm_foreign_ref (foreign
), port
);
260 case SCM_FOREIGN_TYPE_STRUCT
:
261 scm_puts ("struct at 0x", port
);
262 scm_uintprint (SCM_CELL_WORD_1 (foreign
), 16, port
);
264 case SCM_FOREIGN_TYPE_POINTER
:
265 scm_puts ("pointer 0x", port
);
266 scm_uintprint (SCM_FOREIGN_OBJECT_REF (foreign
, scm_t_bits
), 16, port
);
271 scm_putc ('>', port
);
277 scm_init_foreign (void)
279 #ifndef SCM_MAGIC_SNARFER
280 #include "libguile/foreign.x"