Lisp HUG Maillist Archive

FLI again

davef@xanalys.com writes:

>    Strange, it seem my mails don't find their way to this list. 
> 
> Hello Friedrich
> 
> I've not seen (as the list owner) any bounced message from you. It's
> quite common that people attempt to post from addresses which are not
> on the list, when this happens I do inform them.
> 
>    So here we go again: 
>    I have read the Common Lisp cookbbook and looked at how to call an
>    external C function. (example (calling gethostname)
> 
>    Well I extracted that function from the header and let the
>    foreign-parser do the job
> 
>    I than have come up with this (IMHO wrong solution, which should
>    crash)
>    (defun get-hostname ()
>      (let* ((limit 256))
>        (fli:with-dynamic-foreign-objects ((buffer (:char)))
> 	 (let ((ret-val (gethostname buffer limit)))
> 	   (if (> ret-val 0)
> 	       (break)
> 	     (fli:convert-from-foreign-string buffer))))))
> 
> 
>    Well why do I think it should crash? I'm not allocating any space for
>    the external buffer. 

The questions still persists, why doesn't it crash? 

> 
> 
>    I than checked the knowledgebase and bound 17004, but that confuses me
>    even more. 
> 
> Was exactly was it that confused you? The title of Example 2 does seem
> to suggest that a supplied Lisp string can be modified by a foreign
> function call (which is not true) though the text clearly states that
> a new string is returned.
> 
>    So maybe someone can bring into some light.
>    What I want to do
>    I want to allocate a Lisp String (such that it can be handled by the
>    Lisp GC) than I wont to hand this string over to C which fills it well
>    on return it should be still a valid Lisp string.
> 
> Why do you want to first allocate the string in Lisp?
I want Lisps GC to take care of the things. And it's was or is
obviously (wrong?) that it should be the "cheapest" way. Allocate
space for a string one time not more often.

> 
>    What is the right way doing it?
> 
> 
> Here's three definitions which work for me:
> 
> 
> (fli:define-foreign-function (getdomainname-1 "getdomainname" :source)
>    ((:ignore (:reference-return (:ef-mb-string :limit 256)))
why an :ignore?

>     (:constant 256 :integer))
>   )
> 
> 
> 
> (fli:define-foreign-function (%getdomainname "getdomainname" :source)
>     ((buffer :pointer)
>      (len :integer))
>   :result-type :integer)
> 
> (defun getdomainname-2 (len)
>   (fli:with-dynamic-foreign-objects ()
>     (let ((buffer (fli:allocate-dynamic-foreign-object 
>                    :type :char :nelems len)))
>       (when (eq (%getdomainname buffer len) 0)
>         (fli:convert-from-foreign-string buffer :length len)))))
Well in my understanding I have to free the allocated object. If I do
not than it should be a memory leak. What am I missing?

Well now I have some more ways but I still do not understand much
more. So I probably have to rephrase the questions

a) if I use fli:alllcate-dyn... than in my understanding and according
to the docs I have to free that memory by hand.
b) can I do this?
        (let ((str (make-string limit)))
           (fill-str-in-c-function str ...)

     and got it simply back without a new string getting allocated?

c) I do not understand what the "right" solutions should be. Some of
my solutions work although I think they should not! See the first
question. 


So I would appriciate if someone could clarfiy that a bit.

Thanks
Friedrich


Updated at: 2020-12-10 09:02 UTC