mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-12 06:41:13 +02:00
finish ffi docs
* libguile/foreign.c: Some doc tweaks. * doc/ref/api-foreign.texi: Finish FFI docs.
This commit is contained in:
parent
71725997c7
commit
b9264dc5f3
2 changed files with 235 additions and 88 deletions
|
@ -442,9 +442,10 @@ section takes up the problem of accessing C values from Scheme, and the
|
||||||
next discusses C functions.
|
next discusses C functions.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Foreign Types:: foo
|
* Foreign Types:: Expressing C types in Scheme.
|
||||||
* Foreign Variables:: foo
|
* Foreign Variables:: Typed pointers.
|
||||||
* Foreign Pointers and Values:: foo
|
* Void Pointers and Byte Access:: Pointers into the ether.
|
||||||
|
* Foreign Structs:: Packing and unpacking structs.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Foreign Types
|
@node Foreign Types
|
||||||
|
@ -454,9 +455,9 @@ The first impedance mismatch that one sees between C and Scheme is that
|
||||||
in C, the storage locations (variables) are typed, but in Scheme types
|
in C, the storage locations (variables) are typed, but in Scheme types
|
||||||
are associated with values, not variables. @xref{Values and Variables}.
|
are associated with values, not variables. @xref{Values and Variables}.
|
||||||
|
|
||||||
So when accessing a C value from Scheme, we must give the type of the
|
So when accessing a C value through a Scheme pointer, we must give the
|
||||||
value explicitly, as a parameter to any procedure that translates
|
type of the pointed-to value explicitly, as a parameter to any Scheme
|
||||||
between Scheme and C values.
|
procedure that accesses the value.
|
||||||
|
|
||||||
These ``C type values'' may be constructed using the constants and
|
These ``C type values'' may be constructed using the constants and
|
||||||
procedures from the @code{(system foreign)} module, which may be loaded
|
procedures from the @code{(system foreign)} module, which may be loaded
|
||||||
|
@ -469,9 +470,7 @@ like this:
|
||||||
@code{(system foreign)} exports a number of values expressing the basic
|
@code{(system foreign)} exports a number of values expressing the basic
|
||||||
C types:
|
C types:
|
||||||
|
|
||||||
@defvr {Scheme Variable} float
|
@defvr {Scheme Variable} int8
|
||||||
@defvrx {Scheme Variable} double
|
|
||||||
@defvrx {Scheme Variable} int8
|
|
||||||
@defvrx {Scheme Variable} uint8
|
@defvrx {Scheme Variable} uint8
|
||||||
@defvrx {Scheme Variable} uint16
|
@defvrx {Scheme Variable} uint16
|
||||||
@defvrx {Scheme Variable} int16
|
@defvrx {Scheme Variable} int16
|
||||||
|
@ -479,6 +478,8 @@ C types:
|
||||||
@defvrx {Scheme Variable} int32
|
@defvrx {Scheme Variable} int32
|
||||||
@defvrx {Scheme Variable} uint64
|
@defvrx {Scheme Variable} uint64
|
||||||
@defvrx {Scheme Variable} int64
|
@defvrx {Scheme Variable} int64
|
||||||
|
@defvrx {Scheme Variable} float
|
||||||
|
@defvrx {Scheme Variable} double
|
||||||
Values exported by the @code{(system foreign)} module, representing C
|
Values exported by the @code{(system foreign)} module, representing C
|
||||||
numeric types of the specified sizes and signednesses.
|
numeric types of the specified sizes and signednesses.
|
||||||
@end defvr
|
@end defvr
|
||||||
|
@ -499,7 +500,7 @@ numeric types. For example, @code{long} may be @code{equal?} to
|
||||||
@node Foreign Variables
|
@node Foreign Variables
|
||||||
@subsubsection Foreign Variables
|
@subsubsection Foreign Variables
|
||||||
|
|
||||||
Given the types defined in the previous section, foreign values may be
|
Given the types defined in the previous section, C pointers may be
|
||||||
looked up dynamically using @code{dynamic-pointer}.
|
looked up dynamically using @code{dynamic-pointer}.
|
||||||
|
|
||||||
@deffn {Scheme Procedure} dynamic-pointer name type dobj [len]
|
@deffn {Scheme Procedure} dynamic-pointer name type dobj [len]
|
||||||
|
@ -529,12 +530,52 @@ numptob
|
||||||
@result{} #<foreign int32 8>
|
@result{} #<foreign int32 8>
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
A value returned by @code{dynamic-pointer} is a Scheme wrapper for a C
|
||||||
This example shows that a @code{long} on this platform is an
|
pointer, with additional type information. A foreign pointer prints
|
||||||
@code{int32}, and that the value pointed to by @code{numptob} is 8.
|
according to its type. This example showed that a @code{long} on this
|
||||||
|
platform is an @code{int32}, and that the value pointed to by
|
||||||
|
@code{numptob} is 8.
|
||||||
|
|
||||||
@node Foreign Pointers and Values
|
Typed pointers may be referenced using the @code{foreign-ref} and
|
||||||
@subsubsection Foreign Pointers and Values
|
@code{foreign-set!} functions.
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} foreign-ref foreign
|
||||||
|
@deffnx {C Function} scm_foreign_ref foreign
|
||||||
|
Reference the foreign value pointed to by @var{foreign}.
|
||||||
|
|
||||||
|
The value will be referenced according to its type.
|
||||||
|
|
||||||
|
@example
|
||||||
|
(foreign-ref numptob) @result{} 8 ; YMMV
|
||||||
|
@end example
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} foreign-set! foreign val
|
||||||
|
@deffnx {C Function} scm_foreign_set_x foreign val
|
||||||
|
Set the foreign value pointed to by @var{foreign}.
|
||||||
|
|
||||||
|
The value will be set according to its type.
|
||||||
|
|
||||||
|
@example
|
||||||
|
(foreign-set! numptob 120) ; Don't try this at home!
|
||||||
|
@end example
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
If we wanted to corrupt Guile's internal state, we could set
|
||||||
|
@code{scm_numptob} to another value; but we shouldn't, because that
|
||||||
|
variable is not meant to be set. Indeed this point applies more widely:
|
||||||
|
the C API is a dangerous place to be. Not only might setting a value
|
||||||
|
crash your program, simply referencing a value with a wrong-sized type
|
||||||
|
can prove equally disastrous.
|
||||||
|
|
||||||
|
|
||||||
|
@node Void Pointers and Byte Access
|
||||||
|
@subsubsection Void Pointers and Byte Access
|
||||||
|
|
||||||
|
As a special case, a dynamic pointer may be declared to point to type
|
||||||
|
@code{void}, in which case it is treated as a void pointer. A void
|
||||||
|
pointer prints its value as a pointer, without dereferencing the
|
||||||
|
pointer.
|
||||||
|
|
||||||
It's important at this point to conceptually separate foreign values
|
It's important at this point to conceptually separate foreign values
|
||||||
from foreign pointers. @code{dynamic-pointer} gives you a foreign
|
from foreign pointers. @code{dynamic-pointer} gives you a foreign
|
||||||
|
@ -553,8 +594,12 @@ Guile can wrap such a pointer, by declaring that it points to
|
||||||
@code{void}.
|
@code{void}.
|
||||||
|
|
||||||
@defvr {Scheme Variable} void
|
@defvr {Scheme Variable} void
|
||||||
A C type, used when wrapping C pointers. @code{void} represents the type
|
A foreign type value representing nothing.
|
||||||
to which the pointer points.
|
|
||||||
|
@code{void} has two uses: for a foreign pointer, declaring it to be of
|
||||||
|
type @code{void} is like having a @code{void*} in C. For a function, a
|
||||||
|
return type of @code{void} indicates that the function returns no
|
||||||
|
values. A function argument type of @code{void} is invalid.
|
||||||
@end defvr
|
@end defvr
|
||||||
|
|
||||||
As an example, @code{(dynamic-pointer "foo" void bar-lib)} links in the
|
As an example, @code{(dynamic-pointer "foo" void bar-lib)} links in the
|
||||||
|
@ -588,44 +633,83 @@ Mutating the returned bytevector mutates the memory pointed to by
|
||||||
@var{foreign}, so buckle your seatbelts.
|
@var{foreign}, so buckle your seatbelts.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} foreign-set! foreign val
|
@deffn {Scheme Procedure} bytevector->foreign bv [offset [len]]
|
||||||
@deffnx {C Function} scm_foreign_set_x foreign val
|
@deffnx {C Function} scm_bytevector_to_foreign bv offset len
|
||||||
Set the foreign value wrapped by @var{foreign}.
|
Return a foreign pointer aliasing the memory pointed to by
|
||||||
|
@var{bv}.
|
||||||
|
|
||||||
The value will be set according to its type.
|
The resulting foreign will be a void pointer, a foreign whose
|
||||||
|
type is @code{void}. By default it will alias all of the
|
||||||
|
memory pointed to by @var{bv}, from beginning to end.
|
||||||
|
|
||||||
|
Users may explicily specify that the foreign should only alias a
|
||||||
|
subset of the memory, by specifying @var{offset} and @var{len}
|
||||||
|
arguments.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
Typed pointers may be referenced using the @code{foreign-ref} and
|
|
||||||
@code{foreign-set!} functions.
|
|
||||||
|
|
||||||
@deffn {Scheme Procedure} foreign-ref foreign
|
@node Foreign Structs
|
||||||
@deffnx {C Function} scm_foreign_ref foreign
|
@subsubsection Foreign Structs
|
||||||
Reference the foreign value wrapped by @var{foreign}.
|
|
||||||
|
|
||||||
The value will be referenced according to its type.
|
Finally, one last note on foreign values before moving on to actually
|
||||||
|
calling foreign functions. Sometimes you need to deal with C structs,
|
||||||
|
which requires interpreting each element of the struct according to the
|
||||||
|
its type, offset, and alignment. Guile has some primitives to support
|
||||||
|
this.
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} sizeof type
|
||||||
|
@deffnx {C Function} scm_sizeof type
|
||||||
|
Return the size of @var{type}, in bytes.
|
||||||
|
|
||||||
|
@var{type} should be a valid C type, like @code{int}.
|
||||||
|
Alternately @var{type} may be the symbol @code{*}, in which
|
||||||
|
case the size of a pointer is returned. @var{type} may
|
||||||
|
also be a list of types, in which case the size of a
|
||||||
|
@code{struct} with ABI-conventional packing is returned.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} alignof type
|
||||||
|
@deffnx {C Function} scm_alignof type
|
||||||
|
Return the alignment of @var{type}, in bytes.
|
||||||
|
|
||||||
|
@var{type} should be a valid C type, like @code{int}.
|
||||||
|
Alternately @var{type} may be the symbol @code{*}, in which
|
||||||
|
case the alignment of a pointer is returned. @var{type} may
|
||||||
|
also be a list of types, in which case the alignment of a
|
||||||
|
@code{struct} with ABI-conventional packing is returned.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
Guile also provides some convenience methods to pack and unpack foreign
|
||||||
|
pointers wrapping C structs.
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} make-c-struct types vals
|
||||||
|
Create a foreign pointer to a C struct containing @var{vals} with types
|
||||||
|
@code{types}.
|
||||||
|
|
||||||
|
@var{vals} and @code{types} should be lists of the same length.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Scheme Procedure} parse-c-struct foreign types
|
||||||
|
Parse a foreign pointer to a C struct, returning a list of values.
|
||||||
|
|
||||||
|
@code{types} should be a list of C types.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
For example, to create and parse the equivalent of a @code{struct @{
|
||||||
|
int64_t a; uint8_t b; @}}:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(foreign-ref numptob) @result{} 8 ; YMMV
|
(parse-c-struct (make-c-struct (list int64 uint8)
|
||||||
|
(list 300 43))
|
||||||
|
(list int64 uint8))
|
||||||
|
@result{} (300 43)
|
||||||
@end example
|
@end example
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Scheme Procedure} foreign-set! foreign val
|
As yet, Guile only has convenience routines to support
|
||||||
@deffnx {C Function} scm_foreign_set_x foreign val
|
conventionally-packed structs. But given the @code{bytevector->foreign}
|
||||||
Set the foreign value wrapped by @var{foreign}.
|
and @code{foreign->bytevector} routines, one can create and parse
|
||||||
|
tightly packed structs and unions by hand. See the code for
|
||||||
The value will be set according to its type.
|
@code{(system foreign)} for details.
|
||||||
|
|
||||||
@example
|
|
||||||
(foreign-set! numptob 120) ; Don't try this at home!
|
|
||||||
@end example
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
If we wanted to corrupt Guile's internal state, we could set
|
|
||||||
@code{scm_numptob} to another value; but we shouldn't, because that
|
|
||||||
variable is not meant to be set. Indeed this point applies more widely:
|
|
||||||
the C API is a dangerous place to be. Not only might setting a value
|
|
||||||
crash your program, simply referencing a value with a wrong-sized type
|
|
||||||
can prove equally disastrous.
|
|
||||||
|
|
||||||
|
|
||||||
@node Dynamic FFI
|
@node Dynamic FFI
|
||||||
|
@ -644,52 +728,103 @@ procedure that will pass arguments to the foreign function
|
||||||
and return appropriate values.
|
and return appropriate values.
|
||||||
|
|
||||||
@var{arg_types} should be a list of foreign types.
|
@var{arg_types} should be a list of foreign types.
|
||||||
@code{return_type} should be a foreign type.
|
@code{return_type} should be a foreign type. @xref{Foreign Types}, for
|
||||||
|
more information on foreign types.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
TBD
|
Here is a better definition of @code{(math bessel)}:
|
||||||
|
|
||||||
@menu
|
|
||||||
* Foreign Structs::
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
|
|
||||||
@node Foreign Structs
|
|
||||||
@subsubsection Foreign Structs
|
|
||||||
|
|
||||||
Compared to Scheme, C is a lower-level language, but it does have the
|
|
||||||
ability to compose types into structs and unions, so Guile must support
|
|
||||||
these as well.
|
|
||||||
|
|
||||||
Oftentimes one only accesses structures through pointers. In that case,
|
|
||||||
it's easy to use void pointers and the bytevector interface to access
|
|
||||||
structures. However C allows functions to accept and return structures
|
|
||||||
and unions by value, on the stack, so it's necessary to be able to
|
|
||||||
express structure and union types as Scheme values.
|
|
||||||
|
|
||||||
Conventionally-packed st
|
|
||||||
|
|
||||||
As yet, Guile only has support for conventionally-packed structs.
|
|
||||||
tightly-packed structs and unions will
|
|
||||||
|
|
||||||
Note that the Scheme values for C types are just that, @emph{values},
|
|
||||||
not names. @code{(quote int64 uint8)} won't do what you want.
|
|
||||||
|
|
||||||
C does not only have numeric types; one other type that it has is the
|
|
||||||
@dfn{struct}, which in Guile is represented as a list of C types, so
|
|
||||||
that the following two type declarations are equivalent:
|
|
||||||
|
|
||||||
@example
|
@example
|
||||||
struct @{ int64_t foo; uint8_t bar; @}
|
(define-module (math bessel)
|
||||||
(list int64 uint8)
|
#:use-module (system foreign)
|
||||||
|
#:export (j0))
|
||||||
|
|
||||||
|
(define libm (dynamic-link "libm"))
|
||||||
|
|
||||||
|
(define j0
|
||||||
|
(make-foreign-function double
|
||||||
|
(dynamic-func "j0" libm)
|
||||||
|
(list double)))
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Putting Scheme types in a list is the same as declaring a struct type
|
That's it! No C at all.
|
||||||
with the default packing. Guile does not currently support
|
|
||||||
tightly-packed structs; in that case you should declare the value as
|
|
||||||
being a void pointer, and access the bytes as a bytevector.
|
|
||||||
|
|
||||||
|
Numeric arguments and return values from foreign functions are
|
||||||
|
represented as Scheme values. For example, @code{j0} in the above
|
||||||
|
example takes a Scheme number as its argument, and returns a Scheme
|
||||||
|
number.
|
||||||
|
|
||||||
|
Pointers may be passed to and returned from foreign functions as well.
|
||||||
|
In that case the type of the argument or return value should be the
|
||||||
|
symbol @code{*}, indicating a pointer. For example, the following
|
||||||
|
code makes @code{memcpy} available to Scheme:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(define memcpy
|
||||||
|
(let ((this (dynamic-link)))
|
||||||
|
(make-foreign-function '*
|
||||||
|
(dynamic-func "memcpy" this)
|
||||||
|
(list '* '* size_t))))
|
||||||
|
@end example
|
||||||
|
|
||||||
|
To invoke @code{memcpy}, one must pass it foreign pointers:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(use-modules (rnrs bytevector))
|
||||||
|
|
||||||
|
(define src
|
||||||
|
(bytevector->foreign (u8-list->bytevector '(0 1 2 3 4 5 6 7))))
|
||||||
|
(define dest
|
||||||
|
(bytevector->foreign (make-bytevector 16 0)))
|
||||||
|
|
||||||
|
(memcpy dest src (bytevector-length (foreign->bytevector src)))))
|
||||||
|
|
||||||
|
(bytevector->u8-list (foreign->bytevector dest))
|
||||||
|
@result{} (0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
One may also pass structs as values, passing structs as foreign
|
||||||
|
pointers. @xref{Foreign Structs}, for more information on how to express
|
||||||
|
struct types and struct values.
|
||||||
|
|
||||||
|
``Out'' arguments are passed as foreign pointers. The memory pointed to
|
||||||
|
by the foreign pointer is mutated in place.
|
||||||
|
|
||||||
|
@example
|
||||||
|
;; struct timeval @{
|
||||||
|
;; time_t tv_sec; /* seconds */
|
||||||
|
;; suseconds_t tv_usec; /* microseconds */
|
||||||
|
;; @};
|
||||||
|
;; assuming fields are of type "long"
|
||||||
|
|
||||||
|
(define gettimeofday
|
||||||
|
(let ((f (make-foreign-function
|
||||||
|
int
|
||||||
|
(dynamic-func "gettimeofday" (dynamic-link))
|
||||||
|
(list '* '*)))
|
||||||
|
(tv-type (list long long)))
|
||||||
|
(lambda ()
|
||||||
|
(let* ((timeval (make-c-struct tv-type (list 0 0)))
|
||||||
|
(ret (f timeval %null-pointer)))
|
||||||
|
(if (zero? ret)
|
||||||
|
(apply values (parse-c-struct timeval tv-type))
|
||||||
|
(error "gettimeofday returned an error" ret))))))
|
||||||
|
|
||||||
|
(gettimeofday)
|
||||||
|
@result{} 1270587589
|
||||||
|
@result{} 499553
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This example also shows use of @code{%null-pointer}, which is a null
|
||||||
|
foreign pointer, exported by @code{(system foreign)}.
|
||||||
|
|
||||||
|
@defvr {Scheme Variable} %null-pointer
|
||||||
|
A foreign pointer whose value is 0.
|
||||||
|
@end defvr
|
||||||
|
|
||||||
|
As you can see, this interface to foreign functions is at a very low,
|
||||||
|
somewhat dangerous level. A contribution to Guile in the form of a
|
||||||
|
high-level FFI would be most welcome.
|
||||||
|
|
||||||
@c Local Variables:
|
@c Local Variables:
|
||||||
@c TeX-master: "guile.texi"
|
@c TeX-master: "guile.texi"
|
||||||
|
|
|
@ -112,7 +112,7 @@ scm_take_foreign_pointer (scm_t_foreign_type type, void *ptr, size_t len,
|
||||||
|
|
||||||
SCM_DEFINE (scm_foreign_ref, "foreign-ref", 1, 0, 0,
|
SCM_DEFINE (scm_foreign_ref, "foreign-ref", 1, 0, 0,
|
||||||
(SCM foreign),
|
(SCM foreign),
|
||||||
"Reference the foreign value wrapped by @var{foreign}.\n\n"
|
"Reference the foreign value pointed to by @var{foreign}.\n\n"
|
||||||
"The value will be referenced according to its type.")
|
"The value will be referenced according to its type.")
|
||||||
#define FUNC_NAME s_scm_foreign_ref
|
#define FUNC_NAME s_scm_foreign_ref
|
||||||
{
|
{
|
||||||
|
@ -157,7 +157,7 @@ SCM_DEFINE (scm_foreign_ref, "foreign-ref", 1, 0, 0,
|
||||||
|
|
||||||
SCM_DEFINE (scm_foreign_set_x, "foreign-set!", 2, 0, 0,
|
SCM_DEFINE (scm_foreign_set_x, "foreign-set!", 2, 0, 0,
|
||||||
(SCM foreign, SCM val),
|
(SCM foreign, SCM val),
|
||||||
"Set the foreign value wrapped by @var{foreign}.\n\n"
|
"Set the foreign value pointed to by @var{foreign}.\n\n"
|
||||||
"The value will be set according to its type.")
|
"The value will be set according to its type.")
|
||||||
#define FUNC_NAME s_scm_foreign_set_x
|
#define FUNC_NAME s_scm_foreign_set_x
|
||||||
{
|
{
|
||||||
|
@ -426,7 +426,13 @@ scm_i_foreign_print (SCM foreign, SCM port, scm_print_state *pstate)
|
||||||
|
|
||||||
#define ROUND_UP(len,align) (align?(((len-1)|(align-1))+1):len)
|
#define ROUND_UP(len,align) (align?(((len-1)|(align-1))+1):len)
|
||||||
|
|
||||||
SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type), "")
|
SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type),
|
||||||
|
"Return the alignment of @var{type}, in bytes.\n\n"
|
||||||
|
"@var{type} should be a valid C type, like @code{int}.\n"
|
||||||
|
"Alternately @var{type} may be the symbol @code{*}, in which\n"
|
||||||
|
"case the alignment of a pointer is returned. @var{type} may\n"
|
||||||
|
"also be a list of types, in which case the alignment of a\n"
|
||||||
|
"@code{struct} with ABI-conventional packing is returned.")
|
||||||
#define FUNC_NAME s_scm_alignof
|
#define FUNC_NAME s_scm_alignof
|
||||||
{
|
{
|
||||||
if (SCM_I_INUMP (type))
|
if (SCM_I_INUMP (type))
|
||||||
|
@ -468,7 +474,13 @@ SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type), "")
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
SCM_DEFINE (scm_sizeof, "sizeof", 1, 0, 0, (SCM type), "")
|
SCM_DEFINE (scm_sizeof, "sizeof", 1, 0, 0, (SCM type),
|
||||||
|
"Return the size of @var{type}, in bytes.\n\n"
|
||||||
|
"@var{type} should be a valid C type, like @code{int}.\n"
|
||||||
|
"Alternately @var{type} may be the symbol @code{*}, in which\n"
|
||||||
|
"case the size of a pointer is returned. @var{type} may also\n"
|
||||||
|
"be a list of types, in which case the size of a @code{struct}\n"
|
||||||
|
"with ABI-conventional packing is returned.")
|
||||||
#define FUNC_NAME s_scm_sizeof
|
#define FUNC_NAME s_scm_sizeof
|
||||||
{
|
{
|
||||||
if (SCM_I_INUMP (type))
|
if (SCM_I_INUMP (type))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue