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.
#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;
}
#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