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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Chapter 4: An Introduction to Foreign Interfaces and <strong>CFFI</strong> 8<br />

TYPE-OFFSETS is a plist of TYPEs to their integer offsets, as<br />

defined by the CURLOPTTYPE_LONG et al constants in curl.h."<br />

(flet ((enumerated-value (type offset)<br />

(+ (getf type-offsets type) offset)))<br />

‘(progn<br />

(defcenum ,name<br />

,@(loop for (name type number) in enum-args<br />

collect (list name (enumerated-value type number))))<br />

’,name)))<br />

;for REPL users’ sanity<br />

(define-curl-options curl-option<br />

(long 0 objectpoint 10000 functionpoint 20000 off-t 30000)<br />

(:noprogress long 43)<br />

(:nosignal long 99)<br />

(:errorbuffer objectpoint 10)<br />

(:url objectpoint 2))<br />

With some well-placed Emacs query-replace-regexps, you could probably similarly<br />

define the entire CURLoption enumeration. I have selected to transcribe a few that we will<br />

use in this tutorial.<br />

If you’re having trouble following the macrology, just macroexpand the curl-option<br />

definition, or see the following macroexpansion, conveniently downcased and reformatted:<br />

(progn<br />

(defcenum curl-option<br />

(:noprogress 43)<br />

(:nosignal 99)<br />

(:errorbuffer 10010)<br />

(:url 10002))<br />

’curl-option)<br />

That seems more than reasonable. You may notice that we only use the type to compute<br />

the real enumeration offset; we will also need the type information later.<br />

First, however, let’s make sure a simple call to the foreign function works:<br />

cffi-user> (foreign-funcall "curl_easy_setopt"<br />

:pointer *easy-handle*<br />

curl-option :nosignal :long 1 curl-code)<br />

⇒ 0<br />

foreign-funcall, despite its surface simplicity, can be used to call any C function. Its<br />

first argument is a string, naming the function to be called. Next, for each argument, we<br />

pass the name of the C type, which is the same as in defcfun, followed by a <strong>Lisp</strong> object<br />

representing the data to be passed as the argument. The final argument is the return type,<br />

for which we use the curl-code type defined earlier.<br />

defcfun just puts a convenient façade on foreign-funcall. 4 Our earlier call to curlglobal-init<br />

could have been written as follows:<br />

4 This isn’t entirely true; some <strong>Lisp</strong>s don’t support foreign-funcall, so defcfun is implemented without<br />

it. defcfun may also perform optimizations that foreign-funcall cannot.

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

Saved successfully!

Ooh no, something went wrong!