You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Chapter 4: An Introduction to Foreign Interfaces and <strong>CFFI</strong> 14<br />
"Free CURL easy interface HANDLE and any C strings created to<br />
be its options."<br />
(curl-easy-cleanup handle)<br />
(mapc #’foreign-string-free<br />
(gethash handle *easy-handle-cstrings*))<br />
(remhash handle *easy-handle-cstrings*))<br />
(defun add-curl-handle-cstring (handle cstring)<br />
"Add CSTRING to be freed when HANDLE is, answering CSTRING."<br />
(car (push cstring (gethash handle *easy-handle-cstrings*))))<br />
Here we have redefined the interface to create and free handles, to associate a list of allocated<br />
C strings with each handle while it exists. The strategy of using different function names to<br />
wrap around simple foreign functions is more common than the solution implemented earlier<br />
with curry-curl-option-setter, which was to modify the function name’s function slot. 8<br />
Incidentally, the next step is to redefine curry-curl-option-setter to allocate C<br />
strings for the appropriate length of time, given a <strong>Lisp</strong> string as the new-value argument:<br />
(defun curry-curl-option-setter (function-name option-keyword)<br />
"Wrap the function named by FUNCTION-NAME with a version that<br />
curries the second argument as OPTION-KEYWORD.<br />
This function is intended for use in DEFINE-CURL-OPTION-SETTER."<br />
(setf (symbol-function function-name)<br />
(let ((c-function (symbol-function function-name)))<br />
(lambda (easy-handle new-value)<br />
(funcall c-function easy-handle option-keyword<br />
(if (stringp new-value)<br />
(add-curl-handle-cstring<br />
easy-handle<br />
(foreign-string-alloc new-value))<br />
new-value))))))<br />
A quick analysis of the code shows that you need only reevaluate the curl-option enumeration<br />
definition to take advantage of these new semantics. Now, for good measure, let’s<br />
reallocate the handle with the new functions we just defined, and set its URL:<br />
cffi-user> (curl-easy-cleanup *easy-handle*)<br />
⇒ NIL<br />
cffi-user> (setf *easy-handle* (make-easy-handle))<br />
⇒ #<br />
cffi-user> (set-curl-option-nosignal *easy-handle* 1)<br />
⇒ 0<br />
cffi-user> (set-curl-option-url *easy-handle*<br />
"http://www.cliki.<strong>net</strong>/<strong>CFFI</strong>")<br />
⇒ 0<br />
8 There are advantages and disadvantages to each approach; I chose to (setf symbol-function) earlier<br />
because it entailed generating fewer magic function names.