* Intro / Index (last modified: $Date: 2002/03/24 00:20:19 $) This working document explains the design of the libguile API, specifically the interface to the C programming language. Note that this is NOT an API reference manual. - Motivation - History - Decisions - gh_ removal - malloc policy - [add here] * Motivation The file goals.text says: Guile's primary aim is to provide a good extension language which is easy to add to an application written in C for the GNU system. This means that it must export the features of a higher level language in a way that makes it easy not to break them from C code. Although it may no longer be a "primary aim", creating a stable API is important anyway since without something defined, people will take libguile and use it in ad-hoc ways that may cause them trouble later. * History The initial (in ttn's memory, which only goes back to guile-1.3.4) stab at an API was known as the "gh_ interface", which provided "high-level" abstraction to libguile w/ the premise of supporting multiple implementations at some future date. In practice this approach resulted in many gh_* objects being very slight wrappers for the underlying scm_* objects, so eventually this maintenance burden outweighed the (as yet unrealized) hope for alternate implementations, and the gh_ interface was deprecated starting in guile-1.5.x. Starting w/ guile-1.7.x, in concurrence w/ an effort to make libguile available to usloth windows platforms, the naked library was once again dressed w/ the "SCM_API interface". Here is a table of versions (! means planned): guile libguile readline qthreads srfi-4 -13-14 --------------------------------------------------- 1.3.4 6.0.0 0.0.0 0.0.0 - - 1.4 9.0.0 0.0.0 0.0.0 - - 1.4.1 10.0.0 TBD 15.0.0 - - ! 1.6.x 15.0.0 10.0.0 15.0.0 1.0.0 1.0.0 ! Note: These are libtool-style versions: CURRENT:REVISION:AGE * Decisions ** gh_ removal At some point, we need to remove gh_ entirely: guile-X.Y.Z. ** malloc policy Here's a proposal by ela: I would like to propose the follow gh_() equivalents: gh_scm2newstr() -> scm_string2str() in string.[ch] gh_symbol2newstr() -> scm_symbol2str() in symbol.[ch] Both taking the (SCM obj, char *context) and allocating memory via scm_must_malloc(). Thus the user can safely free the returned strings with scm_must_free(). The latter feature would be an improvement to the previous gh_() interface functions, for which the user was told to free() them directly. This caused problems when libguile.so used libc malloc() and the calling application used its own standard free(), which might not be libc free(). It seems to address the general question of: How should client programs use malloc with respect to libguile? Some specific questions: * Do you like the names of the functions? Maybe they should be named scm_c_*() instead of scm_*(). * Do they make sense? * Should we provide something like scm_c_free() for pointers returned by these kind of functions? The first proposal regarding a malloc policy has been rejected for the following resons: That would mean, users of guile - even on non M$ systems - would have to keep track where their memory came from? Assume there are users which have some kind of hash table where they store strings in. The hash table is responsible for removing entries from the table. Now, if you want to put strings from guile as well as other strings into that table you would have to store a pointer to the corresponding version of 'free' with every string? We should demand such coding from all guile users? The proposal itself read: For a clean memory interface of a client program to libguile we use the following functions from libguile: * scm_c_malloc -- should be used to allocate memory returned by some of the SCM to C converter functions in libguile if the client program does not supply memory * scm_c_free -- must be used by the client program to free the memory returned by the SCM to C converter functions in libguile if the client program did not supply a buffer * scm_c_realloc -- to be complete, do not know a real purpose yet Yet another proposal regarding this problem reads as follows: We could make life easier, if we supplied the following: [in gc.h] typedef void * (* scm_t_malloc_func) (size_t); typedef void (* svz_t_free_func) (void *); SCM_API scm_t_malloc_func scm_c_malloc; SCM_API scm_t_free_func scm_c_free; [in gc.c] { /* At some library initialization point. */ scm_c_malloc = malloc; scm_c_free = free; } Then the SCM to C converters allocating memory to store their results use scm_c_malloc() instead of simply malloc(). This way all libguile/Unix users can stick to the previous free() policy, saying that you need to free() pointers delivered by libguile. On the other hand M$-Windows users can pass their own malloc()-function-pointer to the library and use their own free() then. Basically this can be achieved in the following order: { char *str; scm_boot_guile (...); scm_c_malloc = malloc; str = scm_c_string2str (obj, NULL, NULL); free (str); } This policy is still discussed: If there is one global variable scm_c_malloc, then setting it within one thread may interfere with another thread that expects scm_c_malloc to be set differently. In other words, you would have to introduce some locking mechanism to guarantee that the sequence of setting scm_c_malloc and calling scm_string2str can not be interrupted by a different thread that sets scm_c_malloc to a different value.