NextPrevUpTopContentsIndex

4.2.6 Foreign string line terminators

You can specify the line terminator in foreign string conversions via the :eol-style parameter in the external-format argument.

By default foreign strings are assumed to have lines terminated according to platform conventions: Linefeed on Unix/Linux/MacOS, and Carriage-Return followed by Linefeed on Windows. That is, eol-style defaults to :lf and :crlf respectively. This means that unless you take care to specify the external format :eol-style parameter, you may get unexpected string length when returning a Lisp string.

Consider the following C code example on Windows:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
 
__declspec(dllexport) int __cdecl crlf_string(int length, char *string)
{
  int ii;
  int jj;
  for (ii = 0; ii < length ; ii++)
       if (ii % 3 == 1) {
         string[ii] = 10;
         printf("%d\n", ii);
        } else
       if ((ii > 0) && (ii % 3 == 0)) {
         string[ii] = 13;
         printf("%d\n", ii);
        } else
       if (ii % 3 == 2) {
         string[ii] = 97 + rand() % 26 ;
         printf("%d\n", ii);
        }
  string[length] = 0;
  return length;
}

Call this C function from Lisp:

(fli:define-foreign-function (crlf-string 
                              "crlf_string" 
                              :source)
   ((length :int)
    (return-string (:reference-return 
                    (:ef-mb-string 
                     :limit 256
                     :external-format :latin-1))))
 :lambda-list (length &aux return-string)
 :calling-convention :cdecl
 :result-type :int)
 
(multiple-value-bind (length string)
                   (crlf-string 99)
                 (format t "~&C length ~D, Lisp string length ~D~%" length (length string)))
=>
C length 99, Lisp string length 67

Each two character CR LF sequence in the foreign string has been mapped to a single LF character in the Lisp string. If you want to return a Lisp string and not do line terminator conversion, then you must specify the eol-style as in this example:

(fli:define-foreign-function (crlf-string 
                              "crlf_string" 
                              :source)
   ((length :int)
    (return-string (:reference-return 
                    (:ef-mb-string 
                     :limit 256
                     :external-format (:latin-1 :eol-style :lf)))))
 :lambda-list (length &aux return-string)
 :calling-convention :cdecl
 :result-type :int)
 
(multiple-value-bind (length string)
                   (crlf-string 99)
                 (format t "~&C length ~D, Lisp string length ~D~%" length (length string)))
=>
C length 99, Lisp string length 99

LispWorks Foreign Language Interface User Guide and Reference Manual - 14 Mar 2008

NextPrevUpTopContentsIndex