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