Info Node: (g-wrap.info)Defining basic Scheme/C types
(g-wrap.info)Defining basic Scheme/C types
Defining basic Scheme/C types
=============================
For calling C functions from Scheme, a mechanism is needed for checking
the type of Scheme values, converting Scheme values to C values, and
converting C values to Scheme values. The function `make-c-type' is
used for making a type-description object which represents how to do
this for a given Scheme implementation.
- Function: make-c-type c-name fn-convert-to-scm fn-convert-from-scm
fn-scm-is-a
C-NAME is a string indicating the name of the type in C.
FN-CONVERT-TO-SCM is a function which generates an expression to
convert a C value of this type to a Scheme value.
FN-CONVERT-FROM-SCM is a function which generates an expression
convert a Scheme value into a C value of this type. FN-SCM-IS-A
is a function which generates a check for whether a Scheme value
can be converted to this type of C value. It returns `0' for
false and a non-zero value for true.
The "expressions" generated for output to C code are strings, or
lists or trees of strings.
- Function: add-new-type scheme-sym the-type
Associates a type-description object, such as that generated by
`make-c-type', to a symbol so that symbol may be used to refer to
a type in a parameter of a function such as `(new-function ...)'.
- Function: add-type scheme-sym c-type-str fn-to-scm fn-from-scm fn-isa
This both defines the type-description and assigns it to a symbol.
A simple example of how an integer type corresponding to an
immediate number in the Guile might be defined:
(add-type 'int "int"
;fn-convert-to-scm
(lambda (x) (list "SCM_MAKINUM(" x ")"))
;fn-convert-from-scm
(lambda (x) (list "SCM_INUM(" x ")"))
;fn-scm-is-a
(lambda (x) (list "SCM_INUMP(" x ")")))
An example of how type `void' (used for specifying no return value
for a function) might be defined for the Guile interpreter.
(add-type 'void "void"
;fn-convert-to-scm
(lambda (x) "SCM_UNSPECIFIED")
;fn-convert-from-scm
(lambda (x) "(void)")
;fn-scm-is-a
(lambda (x) 1))
- Function: get-type scheme-sym
Returns the type-description object associated with a symbol.
- Function: make-complex-c-type c-name fn-convert-to-scm
fn-convert-from-scm fn-scm-is-a c-cleanup-arg-default?
c-cleanup-ret-default? fn-c-cleanup
WARNING: This function, and the related "cleanup" system should be
considered highly experimental and subject to change up until at
least 1.X of g-wrap is released. Don't use this unless you're
willing to have to re-write everything that depends on it later.
It is currently being tested in GnuCash, but isn't claimed to be
ready for prime-time. Further, in it's final incarnation, it will
probably be a more general mechanism...
This function creates a new g-wrap type corresponding to the C-type
C-NAME. Unlike NEW-TYPE, this function does not have any affect
unless you use ADD-NEW-TYPE to tell g-wrap to add the type to its
list of known types.
The parameters have the following purposes:
C-NAME
the name of the type as far as C is concerned.
FN-CONVERT-TO-SCM
a function returning the C code to be used to convert this
type from a C representation to a Scheme representation.
FN-CONVERT-FROM-SCM
a function returning the C code to be used to convert this
type from a Scheme representation to a C representation.
FN-SCM-IS-A
a function returning the C code to be used to test if a
Scheme object is of this type.
C-CLEANUP-ARG-DEFAULT?
should arguments of this type have their C representations
(the ones created for the purpose of the C-side function
call) be cleaned up just after the call by default?
C-CLEANUP-RET-DEFAULT?
should return values of this type have their C
representations (the ones returned by a C-side function call)
cleaned up just after they are converted to Scheme, but
before the wrapper code returns to Scheme by default?
FN-C-CLEANUP
a function returning the C code to be used to clean up
(destroy, delete, free, whatever) C representations of this
type.
To understand what the cleanup-related arguments do, consider a
typical wrapper call-sequence. First the Scheme wrapper function
is called. Then all of the Scheme arguments are converted to C
representations using the convert-to-scm functions, then the C
function is called with these arguments, and finally, the return
value, if any is converted from its C representation back to a
Scheme value and returned from the wrapper.
The cleanup arguments control the final disposition of the C
representations of the given type when used as arguments and return
values. If an argument is marked as 'cleanup, then just after the
C function returns, the argument will be cleaned up using the
c-cleanup function provided by FN-C-CLEANUP. The same thing
happens to the C representation of the return value just after it
has been converted to a Scheme representation, and just before the
wrapper returns.
An argument or return value is considered to be "marked as
'cleanup" if either C-CLEANUP-ARG-DEFAULT? or
C-CLEANUP-RET-DEFAULT? is not #f respectively, or if the argument
or return value is marked 'cleanup in the options to NEW-FUNCTION.
For more details see Note:Defining a new function.
Deciding when cleanup is appropriate depends on the semantics of
both the type in question and of a given C function. What's
really at issue here is the "ownership" of the C level data
involved. For example, imagine you have a C function that takes a
string pointer as an argument and expects that at the time of the
call, it becomes the "owner" of that pointer, and perhaps it takes
that pointer and stores it in a hash table for later use. If that
particular argument were marked as 'cleanup in g-wrap, as soon as
the C function was called, g-wrap would arrange for it to be
freed, leaving the pointer in the hash table dangling. So for
this particular hypothetical function, the argument in question
needs to be marked as 'no-cleanup, either as the type default
(probably not a good idea for strings in general), or in the
NEW-FUNCTION declaration. For more details see Note:Defining a
new function.
Similar considerations apply to return values. If you had a C
function that returned a constant string pointer from some static
or global table, then it wouldn't be appropriate for the return
value to be marked 'cleanup.
Conversely there may also be types for which 'no-cleanup makes the
most sense as a default, and then 'cleanup would need to be used
in calls to NEW-FUNCTION occasionally. For more details see Note:Defining a new function.
Example:
(add-new-type
'bar
(make-complex-c-type
"bar"
;; fn-convert-to-scm
(lambda (x) (list "bar2scm(" x ")"))
;; fn-convert-from-scm
(lambda (x) (list "scm2bar(" x ")"))
;; fn-scm-is-a
(lambda (x) (list "bar_p(" x ")"))
;; c-cleanup-arg-default?
#t
;; c-cleanup-ret-default?
#t
;; fn-c-cleanup
(lambda (x) (list "free_bar(" x ")"))))