[gambit-list] How to pass a Scheme string to a const char*?

Marc Feeley feeley at iro.umontreal.ca
Mon Dec 12 11:20:10 EST 2011


I finally understand the problem you were explaining.  It is that openlog stores a pointer to the "ident" string that will be used in subsequent calls to syslog.  It does not take a copy of the string.  This means the C string which was converted from Scheme for the first argument of openlog must remain live after the call to openlog returns.

This can be accomplished by incrementing the reference count on the C string when openlog is called, and decrementing the reference count on the closelog call.

The FFI code must change from:

(define openlog
  (c-lambda
   (char-string int int)
   void
   "openlog"))

(define closelog
  (c-lambda () void "closelog"))

to something like this (untested):

(c-declare "static char *temp = NULL;")

(define openlog
  (c-lambda
   (char-string int int)
   void
   "if (temp != NULL) ___EXT(___release_string)(temp);
    temp = ___arg1;
    ___EXT(___addref_string)(___arg1);
    openlog(___arg1,___arg2,___arg3);"))

(define closelog
  (c-lambda
   ()
   void
   "if (temp != NULL) ___EXT(___release_string)(temp);
    closelog();"))

Marc

On 2011-11-21, at 12:43 PM, Vok Vojwo wrote:

> I have defined wrappers for openlog and syslog. The openlog function
> requires an ident string. Whatever I pass to openlog does not survive
> until a call to syslog. I have tried to protect the string with
> ##still-copy (with and without box/unbox) but it does not work. Here
> is the example:
> 
> (define const-ident #f)
> 
> (define openlog
>  (let ((openlog (c-lambda
>                     (char-string int int)
>                     void
>                   "openlog")))
>    (lambda (ident option facility)
>      (set! const-ident (box (##still-copy ident)))
>      (openlog (unbox const-ident) option facility))))
> 
> (define syslog
>  (let ((syslog (c-lambda
>                    (int nonnull-char-string)
>                    void
>                  "syslog")))
>    (lambda (priority . args)
>      (syslog priority (apply string-append args)))))
> 
> This program:
> 
> (define (main . args)
>  (openlog "gambit" (+ LOG_NDELAY LOG_PID) LOG_USER)
>  (syslog LOG_INFO "hello")
>  (closelog))
> 
> will generate random syslog tags:
> 
> Nov 21 17:58:49 sn-e0692 ��*#002[11621]: hello
> 
> What is the correct way to protect a string to be able to pass it to a
> const char* argument?
> _______________________________________________
> Gambit-list mailing list
> Gambit-list at iro.umontreal.ca
> https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list




More information about the Gambit-list mailing list