Suppose you have a C function declared like this:
extern "C" void foo( const char** StringArray);
To call this from Lisp you need to first allocate the foreign memory for each piece of data, that is the array itself and each string. Assuming that
foo
does not capture any of the pointers, you can give this memory dynamic extent as follows:
(defun convert-to-dynamic-foreign-array (strings)
(let* ((count (length strings))
(array
(fli:allocate-foreign-object
:nelems (1+ count) ; assume NULL terminated
:type '(:pointer :char))))
(dotimes (index count)
(setf (fli:dereference array :index index)
(fli:convert-to-dynamic-foreign-string
(elt strings index))))
(setf (fli:dereference array :index count) nil)
array))
(fli:define-foreign-function (%foo foo)
((string-array (:pointer (:pointer :char)))))
(defun foo (strings)
(fli:with-dynamic-foreign-objects () ; provide a dynamic scope
(%foo (convert-to-dynamic-foreign-array strings))))
Here is a similar example converting Lisp strings to
**char
or
*char[]
which by default allocates using
malloc
(the value
:static
for the
allocation
argument):
(defun convert-strings-to-foreign-array (strings &key
(allocation :static))
(let* ((count (length strings))
(array (fli:allocate-foreign-object
:type '(:pointer (:unsigned :char))
:nelems (1+ count)
:initial-element nil
:allocation allocation)))
(loop for index from 0
for string in strings
do (setf (fli:dereference array :index index)
(fli:convert-to-foreign-string
string
:external-format :utf-8
:allocation allocation)))
array))
If you call it frequently, then you will probably want to free the array (and the strings inside it). Alternatively, you can give the array and its strings dynamic scope if the foreign side does not keep a pointer to the data, like this:
(fli:with-dynamic-foreign-objects ()
(let ((array (convert-strings-to-foreign-array
strings :allocation :dynamic)))
(%foo array)))
LispWorks Foreign Language Interface User Guide and Reference Manual - 7 Dec 2011