diff options
-rw-r--r-- | devel/policy/api.text | 64 | ||||
-rw-r--r-- | libguile/ChangeLog | 7 | ||||
-rw-r--r-- | libguile/strings.c | 36 | ||||
-rw-r--r-- | libguile/strings.h | 1 |
4 files changed, 107 insertions, 1 deletions
diff --git a/devel/policy/api.text b/devel/policy/api.text index f59825091..f73dfc6c7 100644 --- a/devel/policy/api.text +++ b/devel/policy/api.text @@ -1,4 +1,4 @@ -* Intro / Index (last modified: $Date: 2001-11-14 20:47:40 $) +* Intro / Index (last modified: $Date: 2001-12-08 12:50:37 $) This working document explains the design of the libguile API, specifically the interface to the C programming language. @@ -74,3 +74,65 @@ malloc with respect to libguile? Some specific questions: * 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. diff --git a/libguile/ChangeLog b/libguile/ChangeLog index 2dd1eb699..4a1e683bc 100644 --- a/libguile/ChangeLog +++ b/libguile/ChangeLog @@ -1,3 +1,10 @@ +2001-12-08 Stefan Jahn <stefan@lkcc.org> + + * strings.c (scm_c_string2str): New function. Converts a + given Scheme string into a C string. Also put in two + THINKME's regarding the malloc policy for the missing converter + routines. + 2001-12-01 Neil Jerram <neil@ossau.uklinux.net> * gh_data.c (gh_module_lookup): Use scm_str2symbol rather than diff --git a/libguile/strings.c b/libguile/strings.c index 680707261..dab7a18f8 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -336,6 +336,42 @@ SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1, } #undef FUNC_NAME +/* Converts the given Scheme string OBJ into a C string, containing a copy + of OBJ's content with a trailing null byte. If LENP is non-NULL, set + *LENP to the string's length. + + When STR is non-NULL it receives the copy and is returned by the function, + otherwise new memory is allocated and the caller is responsible for + freeing it via free(). If out of memory, NULL is returned. + + Note that Scheme strings may contain arbitrary data, including null + characters. This means that null termination is not a reliable way to + determine the length of the returned value. However, the function always + copies the complete contents of OBJ, and sets *LENP to the true length + of the string (if LENP is non-null). */ +char * +scm_c_string2str (SCM obj, char *str, size_t *lenp) +{ + size_t len; + + SCM_ASSERT (SCM_STRINGP (obj), obj, SCM_ARG1, "scm_c_string2str"); + len = SCM_STRING_LENGTH (obj); + + /* THINKME: What malloc policy? */ + if (str == NULL) + str = (char *) malloc ((len + 1) * sizeof (char)); + if (str == NULL) + return NULL; + + memcpy (str, SCM_STRING_CHARS (obj), len); + /* THINKME: Is this necessary for arguments? I do not think so... */ + scm_remember_upto_here_1 (obj); + str[len] = '\0'; + + if (lenp != NULL) + *lenp = len; + return str; +} void scm_init_strings () diff --git a/libguile/strings.h b/libguile/strings.h index e7952cae2..ea1bf7132 100644 --- a/libguile/strings.h +++ b/libguile/strings.h @@ -78,6 +78,7 @@ SCM_API SCM scm_string_set_x (SCM str, SCM k, SCM chr); SCM_API SCM scm_substring (SCM str, SCM start, SCM end); SCM_API SCM scm_string_append (SCM args); SCM_API void scm_init_strings (void); +SCM_API char *scm_c_string2str (SCM obj, char *str, size_t *lenp); |