another try
Strange, it seem my mails don't find their way to this list.
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.
One correct way seem to be:
(defun get-hostname-2 ()
(let ((limit 256))
(fli:with-dynamic-foreign-objects ()
(let* ((buffer (fli:allocate-dynamic-foreign-object :pointer-type
`(:pointer :char)
:nelems
limit))
(ret-val (gethostname buffer limit)))
(if (= ret-val 0)
(fli:convert-from-foreign-string buffer)
(break))))))
Well there may be a better solution available. This seems to be a bit
too ugly. Can anyone give me a hand?
Another thing. It seems the Documenation is wrong. For :ef-mb-string I
find:
:ef-mb-string limit &optional external-format
but trying it in the listener yields this:
The lambda list of foreign type :EF-MB-STRING is (&KEY LIMIT
EXTERNAL-FORMAT (NULL-TERMINATED-P T))
Well this is probably the correct version: Than this should work
(IIUC)
(defun get-hostname-3 ()
(let* ((limit 256)
(buffer (make-string limit)))
(fli:with-dynamic-foreign-objects ((buffer (:ef-mb-string :limit 256
:external-format
:ascii)))
(let ((ret-val (gethostname buffer limit)))
(if (= ret-val 0)
(fli:convert-from-foreign-string buffer)
(break))))))
according to the sources of cl-http tcp-list where one can find this
(defun getdomainname (&optional (where "/etc/defaultdomain"))
(or *domainname*
#+unix
(fli:with-dynamic-foreign-objects ((buffer (:ef-mb-string
:external-format :ascii
:limit 256)))
(and (eql (c-getdomainname
buffer 256) 0)
(setq *domainname*
(fli:convert-from-foreign-string buffer))))
;; Try using DNS name lookup: on some machines this
(let* ((self-name (comm:get-host-entry (machine-instance)
:fields '(:name)))
(dot (and self-name (position #\. self-name))))
(and dot (subseq self-name (1+ dot))))
(if (probe-file where)
(with-open-file (stream where :direction :input)
(setq *domainname* (read-line stream))))
(error 'www-utils:domain-resolver-error)))
I extracted the main logic and got this:
(defun getdomainname (&optional (where "/etc/defaultdomain"))
(or *domainname*
#+unix
(fli:with-dynamic-foreign-objects ((buffer (:ef-mb-string
:external-format :ascii
:limit 256)))
(and (eql (ipc::c-getdomainname buffer 256) 0)
(setq *domainname* (fli:convert-from-foreign-string
buffer))))))
Well this seem to work:
CL-USER 73 : 6 > (getdomainname)
"(none)"
but get-hostname-3 fails with:
(get-hostname-3)
Error: #<Pointer to type (:EF-MB-STRING :LIMIT) = #x0805D090> cannot be
converted to foreign type (:POINTER :CHAR).
1 (abort) Return to level 6.
2 Return to debug level 6.
3 Return to level 5.
4 Return to debug level 5.
5 Try invoking C-GETDOMAI
well than I tried this
(fli:define-foreign-function (c-gethostname "gethostname" :source)
((name :pointer) (len size-t))
:result-type :int
:language :c)
and
(defun get-hostname-4 ()
(let ((limit 256))
(fli:with-dynamic-foreign-objects ((buffer (:reference
(:ef-mb-string
:external-format :ascii
:limit
256))))
(let ((ret-val (c-gethostname buffer limit)))
(if (= ret-val 0)
(fli:convert-from-foreign-string buffer)
(break))))))
this works.
but not
(defun get-hostname-4-1 ()
(let ((limit 256))
(fli:with-dynamic-foreign-objects ((buffer (:reference
(:ef-mb-string
:external-format :ascii
:limit
limit))))
(let ((ret-val (c-gethostname buffer limit)))
(if (= ret-val 0)
(fli:convert-from-foreign-string buffer)
(break))))))
WellI got the messag that limit is not bound. But it is!
but again the queston is should it?
I than checked the knowledgebase and bound 17004, but that confuses me
even more.
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.
What is the right way doing it?
Thanks
Friedrich