27.11.2014 Views

CFFI User Manual - Common Lisp.net

CFFI User Manual - Common Lisp.net

CFFI User Manual - Common Lisp.net

SHOW MORE
SHOW LESS

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.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!