This is g-wrap.info, produced by makeinfo version 4.2 from g-wrap.texi.  File: g-wrap.info, Node: Accessing the wrapped API from the target language, Next: Coping With Old Guile Versions, Prev: Generating the glue code, Up: Generating and using the glue code Interfacing the library and glue code to the interpreter ======================================================== The methods for integrating support for a g-wrapped API into various target languages vary, so these will have to be dealt with on a case by case basis. At the moment only the primitive tool g-wrap-config is documented here. It can provide the information needed for linking g-wrap into a target executable for each of the languages g-wrap supports (presuming linking even makes sense). Consider this entire area one that's still under development, so expect the details to change. Right now code can be statically linked to the interpreters, or loaded dynamically as shared libraries. To find out which libraries are required use the g-wrap-config command. It may be invoked as follows: `g-wrap-config --version' show version information `g-wrap-config --help' show this message `g-wrap-config --c-compile-args LANGUAGE' C compile args for LANGUAGE `g-wrap-config --c-link-args LANGUAGE' C link args for LANGUAGE `g-wrap-config --c-static-link-args LANGUAGE' C static link args for LANGUAGE where (at the moment) LANGUAGE may be either rscheme or guile. Examples for each of the target languages will be available in the distribution. This infrastructure is probably not sufficient in the long run if g-wrap is extended to support many languages, but it's a start, and it handles the current scope fairly well.  File: g-wrap.info, Node: Coping With Old Guile Versions, Prev: Accessing the wrapped API from the target language, Up: Generating and using the glue code Coping With Old Guile Versions ============================== The guile interface for dealing with pointers was changed between version 1.3 and subsequent releases (including 1.3.4), and g-wrap was changed to use the new interface. However, as some older distributions still use guile 1.3 it has been necessary to keep the option of the old interface available. If you only use 1.3.4 or later versions of guile, you can safely ignore this section. To use the old interface, make sure the C constant GWRAP_OLD_GUILE_SMOB is defined when compiling the generated C file. If you are using autoconf, a macro AC_GWRAP_CHECK_GUILE, with no arguments, is provided in g-wrap.m4. It checkes which version of guile is available, and if necessary sets GWRAP_OLD_STYLE_SMOB. If you use it, make sure to include the line #undef GWRAP_OLD_STYLE_SMOB in either acconfig.h, or config.h.in, depending on how you are using autoconf. Of course, if you do this, you must ensure config.h is #included when you compile the generated C file! For more details on autoconf see its extensive documentation. NOTE: we can't guarantee that old versions of guile will be supported forever. We will try to ensure that most of the versions currently being distributed work, but we're not in a position to keep multiple layers of compatability code.  File: g-wrap.info, Node: Types available by default, Next: Extending g-wrap and porting it to other Scheme implementations, Prev: Generating and using the glue code, Up: Top Types available by default ************************** By default g-wrap supports the following types. Each may be used as the TYPE-SYM in calls to `new-function': * Menu: * Guile Types:: * RScheme Types::  File: g-wrap.info, Node: Guile Types, Next: RScheme Types, Prev: Types available by default, Up: Types available by default Guile Types =========== `void' nothing, on both the C and Scheme sides. `char' a C `char' and a Scheme character. `int' a C `int' and a Scheme number. `unsigned-int' a C `unsigned int' and a Scheme number. `unsigned-long' a C `unsigned long' and a Scheme number. `unsigned-long-long' a C `unsigned long long' and a Scheme number. `float' a C `float' and a Scheme number. `double' a C `double' and a Scheme number. `bool' a C `int' and a Scheme boolean. `string-as-symbol' a C `char *' and a Scheme symbol. This type lets you pass symbols to C as strings and get them back as symbols. Note that by default it is assumed that C returns freshly malloced strings, so they'll be deleted immediately. You can override this on a per function basis with the 'no-cleanup option. For details see the description of `make-complex-c-type' in the section on *Note Defining basic Scheme/C types::. WARNING, this type is new and subject to change. Don't rely on it unless you're willing to possibly have to rewrite your spec file a bit when things stablize. `const-string' a C `char *' and a Scheme string. This type lets you pass strings from Scheme to C and back, but bear in mind that by default, it takes the conservative (but leaky) position of assuming that the C code might store for later use any strings passed in as arguments, and might pass back as return values strings that are shared elsewhere, or for some other reason cannot be disposed of. This means that g-wrap will not, by default free the strings it allocates to pass to the underlying C function as parameters, and it will not free any string that the C function might return. You can override this behavior on a per function basis with the 'cleanup option; for details see the description of `make-complex-c-type' in the section on *Note Defining basic Scheme/C types::. WARNING, the cleanup functionality is new and subject to change. Don't rely on it unless you're willing to possibly have to rewrite your spec file a bit when things stablize. FIXME: we need a node covering memory allocation. Combine it with the final node discussing garbage collection. In the end we need a more general approach in g-wrap. `tSCM' This is a "transparent" type that allows you to pass a Scheme object directly to a C function, or receive one as a return value through the standard Guile SCM type. The Guile side also supports pointer tokens and pointer arrays. For more information, see *Note Pointer Tokens and Pointer Arrays::. * Menu: * Pointer Tokens and Pointer Arrays::  File: g-wrap.info, Node: Pointer Tokens and Pointer Arrays, Prev: Guile Types, Up: Guile Types Pointer Tokens and Pointer Arrays --------------------------------- WARNING: Like the "cleanup" functionality, pointer tokens and pointer arrays 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, we probably need a more coherent mechanism. As it stands this is a first draft, and things are added as needed. That said, pointer tokens and pointer arrays provide a method for handling C pointers as arguments and return values. Pointer tokens handle pointers to C structures and pointer arrays handle C arrays of pointers. * Menu: * Pointer Tokens:: * Pointer Arrays::  File: g-wrap.info, Node: Pointer Tokens, Next: Pointer Arrays, Prev: Pointer Tokens and Pointer Arrays, Up: Pointer Tokens and Pointer Arrays Pointer Tokens .............. Before deciding to use pointer tokens, please see the warning here *Note Pointer Tokens and Pointer Arrays::. Pointer tokens provide a method for handling pointers to C structures. For example, if you had a C function that took as an argument a Lead* and returned a Gold*, you could tell g-wrap how to handle these pointers and related functions. (make-pointer-token-type 'Lead* "Lead*") (make-pointer-token-type 'Gold* "Gold*") (new-function 'frobnicate 'Gold* "frobnicate" '((Lead* lead)) "Frobnicate.") The calls to `make-pointer-token-type' tell g-wrap to create a Scheme level object for each type that can hold the lower level C pointer at the Scheme level. Pointer token objects are represented as opaque objects (SMOBs actually). You can pass them around to wrapped C functions, and there are some support functions for manipulating them that are detailed below. You can't directly create pointer tokens at the Scheme level. Right now, they're only created as the return values of C level functions. Null pointers are just represented by #f. If a wrapped function tries to return a null pointer, g-wrap will convert it to #f, and if you pass in #f to a function that expects a pointer token then g-wrap will arrange for a null pointer to be passed to the underlying wrapped function. The pointer token items themselves are garbage collected, as you would expect, but the pointers they contain are never touched directly by the g-wrap subsystems, so it's up to you (or the functions being called) to handle de-allocation of the associated C-level Foo* pointers. This will usually be handled by some sequence like this: (define bar (c-func-to-create-foo-pointer)) (c-func-to-manipulate-foo-pointer bar) (c-func-to-destroy-foo-pointer bar) FIXME: There are also some functions available at the C level for manuipulating pointer tokens from there, but at the moment those functions are not documented.  File: g-wrap.info, Node: Pointer Arrays, Prev: Pointer Tokens, Up: Pointer Tokens and Pointer Arrays Pointer Arrays .............. Before deciding to use pointer arrays, please see the warning here *Note Pointer Tokens and Pointer Arrays::. Pointer arrays provide a method for handling arrays of C pointers to structures. At the moment, pointer arrays presume null terminated arrays of pointers at the C level. This is a result of the fact that they were originally implemented to handle an interface that uses null terminated arrays heavily. Eventually pointer arrays will be extended to handle both null terminated and non-null terminated arrays, probably with two separate types. This may mean backward-incompatible API renaming/changes, so be warned. Null array pointers are just represented by #f. If a wrapped function tries to return a null array pointer, g-wrap will convert it to #f, and if you pass in #f to a function that expects a pointer array then g-wrap will arrange for a null array pointer to be passed to the underlying wrapped function. As an example, pretend you have a C function that takes as an argument an array of Lead* items (i.e. it has an argument of C type Lead**) and returns an array of Gold* items, you can tell g-wrap how to handle these pointers and related functions like this: (make-pointer-array-type 'Lead** "Lead**") (make-pointer-array-type 'Gold** "Gold**") (new-function 'frobnicate 'Gold** "frobnicate" '((Lead** lead)) "Frobnicate.") The calls to `make-pointer-array-type' tell g-wrap to create a Scheme level object for each type that can hold the lower level C pointer array at the Scheme level. At the Scheme level, pointer array objects are represented as opaque objects (SMOBs actually). You can pass them around to wrapped C functions, and there are some support functions for manipulating them that are detailed below, but you can't directly create pointer arrays at the Scheme level. Right now, they're only created as the return values of C level functions. The pointer array items themselves are garbage collected, as you would expect, but the pointers they contain are never touched directly by the g-wrap subsystems, so it's up to you (or the functions being called) to handle de-allocation of the associated C-level Foo** array objects. This will usually be handled by some sequence like this: (define bar (c-func-to-create-foo-array)) (c-func-to-manipulate-foo-arrays bar) (c-func-to-destroy-foo-arrays bar) G-wrap will handle arranging for the Scheme level pointer wrappers to be cleaned up by the garbage collector. In addition to passing pointer arrays as parameters and receiving them as return values, the following functions are available at the Scheme level. Note that right now, as mentioned above, all of the code presumes that the pointer arrays are null terminated, so if your C code's not set up to work thi way, then you can't use this functionality just yet. - Function: pointer-array-ref pointer-array index Returns a pointer-token representing the C level pointer at the given index in the pointer-array (uses zero-indexing). Right now there is no range checking on the index, so you can ask for a bogus pointer. - Function: pointer-array-length pointer-array Returns the number of items in the pointer-array. FIXME: There are also some functions available at the C level for manuipulating pointer tokens from there, but at the moment those functions are not documented.  File: g-wrap.info, Node: RScheme Types, Prev: Guile Types, Up: Types available by default RScheme Types ============= FIXME: not documented yet...  File: g-wrap.info, Node: Extending g-wrap and porting it to other Scheme implementations, Next: Portable "Fancy tricks", Prev: Types available by default, Up: Top Extending g-wrap and porting it to other Scheme implementations *************************************************************** To expand the ability of g-wrap to generate glue code for a given interpreter, you may want to add support for more Scheme data types. This is (usually) a simple process if you understand the internal details of how the interpreter deals with the type in question. * Menu: * Defining basic Scheme/C types::  File: g-wrap.info, Node: Defining basic Scheme/C types, Prev: Extending g-wrap and porting it to other Scheme implementations, Up: Extending g-wrap and porting it to other Scheme implementations 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 ")"))))  File: g-wrap.info, Node: Portable "Fancy tricks", Prev: Extending g-wrap and porting it to other Scheme implementations, Up: Top Additional issues ***************** The most difficult issue with wrapping a C library for use with a Scheme interpreter seems to be the issue of memory management. g-wrap does not try to deal much with this issue because it is a messy one. One assumption made by the code generator is that objects are maintained in the Scheme world--when the interpreter no longer references an object, it may be garbage-collected and de-allocated. Another assumption _is that any object returned by a call to a C function is a new object_ which the interpreter will wrap in a new Scheme object. If this is not true, then it is possible for multiple Scheme objects to refer to a single C object, and serious errors can occur. I have written code which uses some fancy tricks to get around this problem for certain specific cases, but there is no simple way to deal with this problem in general without the C library to have specific support for helping the interpreter out. Future versions of g-wrap may incorporate some support for helping the C library cooperate with this issue by storing the Scheme representation of an object inside the object itself. * Menu: * add-new-type: Defining basic Scheme/C types. * add-type <1>: Defining basic Scheme/C types. * add-type: Adding a new type. * get-type: Defining basic Scheme/C types. * gw_error: Utility functions. * gw_puts: Utility functions. * gwrap-assume-types-wrapped: Other functions needed for describing the library glue code. * gwrap-close-module: Other functions needed for describing the library glue code. * gwrap-generate-wrapped-header: Other functions needed for describing the library glue code. * gwrap-include-global-header: Other functions needed for describing the library glue code. * gwrap-include-local-header: Other functions needed for describing the library glue code. * gwrap-open-module: Other functions needed for describing the library glue code. * gwrap-scan-source-file: Scanning source code for functions to export. * make-c-type: Defining basic Scheme/C types. * make-complex-c-type: Defining basic Scheme/C types. * new-constant: Defining a new constant. * new-function: Manually defining functions. * new-type: Adding a new type. * pointer-array-length: Pointer Arrays. * pointer-array-ref: Pointer Arrays.