NextPrevUpTopContentsIndex

4.2.7 Mapping Nil to a Null Pointer

If you wish a string argument to accept nil and pass it as a null pointer, or to return a null pointer as Lisp value nil , use the :allow-null argument to the :reference types.

The C function strcap in the following example modifies a string, but also accepts and returns a null pointer if passed.

Windows version:

#include <string.h>
#include <ctype.h>
 
__declspec(dllexport) char* __cdecl strcap(char *string)
{
  int len;
  int ii;
  if (string) {
     len = strlen(string);
     if (len > 0) {
        for (ii = len - 1; ii > 0; ii--)
            if (isupper(string[ii]))
               string[ii] = tolower(string[ii]); 
        if (islower(string[0]))
           string[0] = toupper(string[0]);
     }
  }
  return string;
}

Linux/Unix/Macintosh version:

#include <string.h>
#include <ctype.h>
 
char* strcap(char *string)
{
  int len;
  int ii;
  if (string) {
     len = strlen(string);
     if (len > 0) {
        for (ii = len - 1; ii > 0; ii--)
            if (isupper(string[ii]))
               string[ii] = tolower(string[ii]); 
        if (islower(string[0]))
           string[0] = toupper(string[0]);
     }
  }
  return string;
}

With this following foreign function definition:

(fli:define-foreign-function (strcap "strcap" :source)
    ((string (:reference :ef-mb-string)))
  :language
  :c
  :calling-convention
  :cdecl)
(strcap "abC")
=>
"Abc"

However (strcap nil) signals error because the :ef-mb-string type expects a string.

Using :allow-null allows nil to be passed:

(fli:define-foreign-function (strcap "strcap" :source)
    ((string (:reference :ef-mb-string :allow-null t)))
  :language
  :c
  :calling-convention
  :cdecl)
(strcap nil) 
=>
nil

Note that with-foreign-string, convert-to-foreign-string and convert-from-foreign-string also accept an :allow-null argument. So another way to call strcap and allow the null pointer is:

(fli:define-foreign-function (strcap "strcap" :source)
    ((string :pointer))
  :language
  :c
  :calling-convention
  :cdecl)
 
(defun c-string-capitalize (string)
  (fli:with-foreign-string (ptr elts bytes :allow-null t)
      string
    (declare (ignore  elts bytes))
    (strcap ptr)
    (fli:convert-from-foreign-string ptr :allow-null t)))
 
(c-string-capitalize "abC")
=>
"Abc"
 
(c-string-capitalize nil)
=>
nil

LispWorks Foreign Language Interface User Guide and Reference Manual - 27 Mar 2005

NextPrevUpTopContentsIndex