Home

CFFI User Manual - Common

image

Contents

1. 0 005 9 abstractions in O el else ds heh med 4 advantages of FFI esssseeeeseeeeeeeA 4 B benefits of EFI iste dea Re 4 Dbitfreld eli Eh Gate tae ea 116 breaking the abstraction 0 9 C C abstractionsS i2iiuols lido eie ae lads 4 callback definition 0 00 ccc cece eee 16 callback symbol pointer 110 calling foreign functions 0 6 121 CC flagS elxs d ee seg ane oa bb Ee edere 115 Cenum rests EE E EES EEEE TEET ETE 115 close foreign library library success 99 compiler macros for type translation 26 CONStaNtss assesses cep ea 114 consta nt num ee cle ese wee nen 115 convert from foreign foreign value type Valu6n onastehtreeensnbied eb dane ides 29 convert to foreign value type foreign value alloc params 30 einn EET 115 cstruct and class vol le aa tees tes 115 ung M L 114 CUMION 23d oec pie eR muU quU tes a DEM NUS 115 GUI EU emper PPS EP PI IUE MSS 5 CVAT ee E e sedis uo dd ue EATE 115 data in Lisp and C 0 eee eee eee eee 18 defbitfield name and options amp body masks 31 defcallback name and options return type arguments amp body body name 111 defcenum name and options amp body enum list E 37 defcfun name and options return type amp body docstring arguments amp rest gt lisp name i e
2. if varp intern format nil a name name gt lt STANDARD METHOD TRANSLATE NAME FROM FOREIGN STRING EQL lt Package SOME PACKAGE gt CFFI gt defcfun someXmlFunction SOME XML FUNCTION See Also defcfun page 89 translate camelcase name page 94 translate name to foreign page 96 translate underscore separated name page 97 Chapter 10 Functions 96 translate name to foreign Syntax translate name to foreign lisp name package optional varp Function string Arguments and Values lisp name A symbol naming the Lisp function to be created package A Lisp package varp A generalized boolean string The string representing the foreign function name Description translate name to foreign is used by defefun page 89 to handle the conversion of lisp names to foreign names By default it translates using translate underscore separated name page 97 However you can create specialized methods on this function to make translating more closely match the foreign library s naming conventions Specialize package on some package This allows other packages to load libraries with different naming conventions Examples CFFI gt defcfun some xml function gt gome xml function CFFI gt defmethod translate name to foreign spec symbol package eql package amp optional varp let name translate camelcase name spec if varp subseq name 1 1 length name name g
3. Examples CFFI gt foreign type alignment char 1 CFFI gt foreign type alignment short gt 2 CFFI gt foreign type alignment int gt 4 defcstruct foo a char CFFI gt foreign type alignment struct foo gt 1 See Also foreign type size page 49 Chapter 6 Foreign Types 49 foreign type size Syntax foreign type size type gt size Function Arguments and Values type A foreign type size An integer Description The function foreign type size return the size of type in bytes This includes any padding within and following the in memory representation as needed to create an array of type objects Examples defcstruct foo a double c char CFFI gt foreign type size double gt 8 CFFI gt foreign type size char gt 1 CFFI gt foreign type size struct foo gt 16 See Also foreign type alignment page 48 Chapter 6 Foreign Types 50 free converted object Syntax free converted object foreign value type params Function Arguments and Values foreign value The C object to be freed type A CFFI type specifier params The state returned as the second value from convert to foreign used to implement the third argument to free translated object Description The return value is unspecified This is an external interface to the type translation facility In the implementation all foreign functions are ultimately defined as type translation
4. Chapter 4 An Introduction to Foreign Interfaces and CFFI 10 cluttered than the equivalent disjoint function set would be in addition setting a new option in an old libcurl can generate a run time error rather than breaking the compile Lisp can just as concisely generate functions as compare values and the undefined function error is just as useful as any explicit error we could define here might be 4 7 Option functions in Lisp We could use foreign funcall directly every time we wanted to call curl_easy_setopt However we can encapsulate some of the necessary information with the following We will use this type later in a more creative way For now just consider it a marker that this isn t just any pointer defctype easy handle pointer defmacro curl easy setopt easy handle enumerated name value type new value Call curl_easy_setopt on EASY HANDLE using ENUMERATED NAME as the OPTION VALUE TYPE is the CFFI foreign type of the third argument and NEW VALUE is the Lisp data to be translated to the third argument VALUE TYPE is not evaluated foreign funcall curl easy setopt easy handle easy handle curl option enumerated name value type new value curl code Now we define a function for each kind of argument that encodes the correct value type in the above This can be done reasonably in the define curl options macroexpansion after all that is where the different options are listed
5. The foreign string free function frees a foreign string allocated by foreign string alloc Examples See Also foreign string alloc page 78 Chapter 8 Strings 80 foreign string to lisp Syntax foreign string to lisp ptr amp key offset count max chars Function encoding string Arguments and Values ptr A pointer offset An integer greater than or equal to 0 Defauls to 0 count Either nil the default or an integer greater than or equal to 0 max chars An integer greater than or equal to 0 1 array total size limit by default encoding Foreign encoding Defaults to default foreign encoding string A Lisp string Description The foreign string to lisp function converts at most count octets from ptr into a Lisp string using the defined encoding If count is nil the default characters are copied until max chars is reached or a NULL character is found If ptr is a null pointer returns nil Note that the string type will automatically convert between Lisp strings and foreign strings Examples CFFI gt foreign funcall getenv string HOME pointer lt FOREIGN ADDRESS xBFFFFFD5 gt CFFI gt foreign string to lisp gt Users luis See Also llisp string to foreign page 81 foreign string alloc page 78 Chapter 8 Strings 81 lisp string to foreign Syntax lisp string to foreign string buffer bufsize amp key start Function end offset encoding buffer Argu
6. ie ak nacre pasa wath ERE anai 9 Cine ETT 14 DBWIG 2cubeigie ere p ERREUR a tnd aston EDS PRISE 4 translate camelcase name name amp key upper initial p special words return value oc c4 rie it LE eae 94 translate from foreign foreign value type name lisp value 52 Index translate into foreign memory lisp value type name pointer 0 54 translate name from foreign foreign name package amp optional varp symbol 95 translate name to foreign lisp name package amp optional varp string 96 translate to foreign lisp value type name gt foreign value alloc param 53 translate underscore separated name name return val e eseseiicca e i hen OF translating typ8 w anne sana 18 tutorial CFFI os 20 2 4 2a 4 type definition 22r es een 18 type translators optimizing 26 U use foreign library name 108 123 rs p HR Y with foreign object var type amp optional count amp body body 2 000 74 with foreign objects bindings amp body body E 74 with foreign pointer var size koptional size var amp body body 75 with foreign pointer as string var size amp optional size var amp rest args amp body body gt string en eee Bae 83 with foreign slots vars ptr type amp body body DAM A toby edt hwy ee ees 55 with foreign string
7. progn constant ev enable EV_ENABLE constant ev disable EV_DISABLE include amp rest files Grovel Form Include the specified files specified as strings in the generated C source code in package symbol Grovel Form Set the package to be used for the final Lisp output ctype lisp name size designator Grovel Form Define a CFFI foreign type for the string in size designator e g ctype pid pid_ t constant lisp name amp rest c names amp key type documentation Grovel Form optional Search for the constant named by the first c name string found to be known to the C preprocessor and define it as lisp name Chapter 13 The Groveller 115 The type keyword argument specifies how to grovel the constant either integer the default or double float If optional is true no error will be raised if all the c names are unknown If lisp name is a keyword the actual constant will be a symbol of the same name interned in the current package define name amp optional value Grovel Form Defines an additional C preprocessor symbol which is useful for altering the behavior of included system headers cc flags amp rest flags Grovel Form Adds cc flags to the command line arguments used for the C compiler invocation pkg config cflags pkg amp key optional Grovel Form Adds pkg to the command line arguments for the external program pkg config and runs it to retrieve the relevant include flags used for the C compil
8. Using asdf to load systems in asdf another system definition facility for information on asdf central registry See mini eval in libraries lisp for the source of this definition As is always the case with a Lisp eval it s easier to understand the Lisp definition than the english Chapter 11 Libraries 104 pushnew P home sirian lisp libli foreign library directories test equal load foreign library default liblibli The following example would achieve the same effect pushnew merge pathnames p lisp libli user homedir pathname foreign library directories test equal gt MERGE PATHNAMES P lisp libli USER HOMEDIR PATHNAME load foreign library default liblibli See also darwin framework directories page 100 define foreign library page 101 Chapter 11 Libraries 105 load foreign library Syntax load foreign library library designator library Function Arguments and Values library designator A library designator library designator An instance of foreign library Description Load the library indicated by library designator A library designator is defined as follows 1 If a symbol is considered a name previously defined with define foreign library 2 Ifastring or pathname passed as a namestring directly to the implementation s foreign library loader If that fails search the directories in foreign library directories with cl pr
9. defun get easy handle error handle Answer a string containing HANDLE s current error message foreign string to lisp slot value handle error buffer defun free easy handle handle Free CURL easy interface HANDLE and any C strings created to be its options 10 Tt might be better to return values than curle ok in real code but this is good for illustration Chapter 4 An Introduction to Foreign Interfaces and CFFI 20 with slots pointer error buffer c strings handle curl easy cleanup pointer foreign free error buffer mapc foreign string free c strings define foreign type easy handle type O actual type pointer simple parser easy handle defmethod translate to foreign handle type easy handle type Extract the pointer from an easy HANDLE slot value handle pointer While we changed some of the Lisp functions defined earlier to use CLOS slots rather than hash tables the foreign functions work just as well as they did before The greatest strength and the greatest limitation of the type translator comes from its generalized interface As stated previously we could define all foreign function calls in terms of the primitive foreign types provided by CFFI The type translator interface allows us to cleanly specify the relationship between Lisp and C data independent of where it appears in a function call This independence comes at a price for example it cannot be used to mo
10. name amp key read only library default name lisp name foreign name foreign name lisp name Arguments and Values foreign name A string denoting a foreign function lisp name A symbol naming the Lisp function to be created type A foreign type read only A boolean documentation A Lisp string not evaluated Description The defcvar macro defines a symbol macro lisp name that looks up foreign name and dereferences it acording to type It can also be setfed unless read only is true in which case an error will be signaled When one of lisp name or foreign name is omitted the other is automatically derived using the following rules e Foreign names are converted to Lisp names by uppercasing replacing underscores with hyphens and wrapping around asterisks e Lisp names are converted to foreign names by lowercasing replacing hyphens with underscores and removing asterisks if any Examples CFFI gt defcvar errno int ERRNO CFFI gt foreign funcall strerror int errno string Inappropriate ioctl for device CFFI gt setf errno 1 gt 1 CFFI gt foreign funcall strerror int errno string Operation not permitted Trying to modify a read only foreign variable CFFI gt defcvar errno error number read only t int gt ERROR NUMBER CFFI gt setf error number 12 gt Trying to modify read only foreign var ERROR NUMBER Note that accessing errno this way won
11. 2 3 Implementation Support 3 3 1 La mitations sesseeeee RR RR Rs 3 An Introduction to Foreign Interfaces and oy errr eee S e E 4 4 1 What makes Lisp different 00000 e cece eee eens 4 4 2 Getting a URL ea RR DUI Ee 5 4 3 Loading foreign libraries 0 000 eee eee eee 5 AA Initializing Libeurl u 22a este 6 4 5 Setting download options 0 0 eee eee eee T 4 6 Breaking the abstraction 0 cece eee eee eee eee 9 4 7 Option functions in Lisp 2 e cee eee eee eee 10 4 8 Memory management 0 cece eee een 12 4 9 Calling Lisp from C 0 een eee nna 15 4 10 A complete FFI 0 kiat edendi 17 4 11 Defining new types 0 cece eect eee eee eens 18 4 12 What s next 2 222 222 Hanna es OE DREREREI RR 20 Wrapper generators usseesss 21 Foreign Types uuseeeeee sess 22 6 1 Builteln Types axo ec eee ana en oes 22 6 2 Other Types e adeo ea a a 23 6 3 Defining Foreign Types sseeeessseeee errn nr rren 24 6 4 Foreign Type Translators 0 c cece eee eens 25 6 5 Optimizing Type Translators seeeeeeeeeeeeeeee 26 6 6 Foreign Structure Types lsssesesssseee e 28 6 7 Allocating Foreign Objects 00 e cee cece eee teens 28 Pointers ee dolce oar ice ardor ened 57 7 1 Basic Pointer Operations 0 0 c cece ences 5T 7 2 Alloc
12. NIL See Also make pointer page 65 null pointer p page 70 Chapter 7 Pointers 72 pointer address Syntax pointer address ptr address Function Arguments and Values ptr A foreign pointer address An integer Description The function pointer address will return the address of a foreign pointer ptr Examples CFFI gt pointer address null pointer gt 0 CFFI gt pointer address make pointer 123 gt 123 See Also make pointer page 65 inc pointer page 63 null pointer page 69 null pointer p page 70 pointerp page 71 pointer eq page 73 mem ref page 68 Chapter 7 Pointers 73 pointer eq Syntax pointer eq ptri ptr2 gt boolean Function Arguments and Values ptrl ptr2 A foreign pointer boolean T or NIL Description The function pointer eq returns true if ptrl and ptr2 point to the same memory address and false otherwise Implementation specific Notes The representation of foreign pointers varies across the various Lisp implementations as does the behaviour of the built in Common Lisp equality predicates Comparing two pointers that point to the same address with EQ Lisps will return true on some Lisps others require more general predicates like EQL or EQUALP and finally some will return false using any of these predicates Therefore for portability you should use POINTER EQ Examples This is an example using SBCL see the implementation specific notes abov
13. a slot in the structure type object The object contained in the slot specified by slot name Description For simple slots foreign slot value returns the value of the object such as a Lisp integer or pointer In C this would be expressed as ptr gt slot For aggregate slots a pointer inside the structure to the beginning of the slot s data is returned In C this would be expressed as amp ptr gt slot This pointer and the memory it points to have the same extent as ptr There are compiler macros for foreign slot value and its setf expansion that open code the memory access when type and slot names are constant at compile time Examples defcstruct point Pointer structure x int y int CFFI gt with foreign object ptr struct point Initialize the slots setf foreign slot value ptr struct point x 42 foreign slot value ptr struct point y 42 Return a list with the coordinates with foreign slots x y ptr struct point list x y gt 42 42 See Also defestruct page 33 foreign slot names page 44 foreign slot offset page 45 foreign slot pointer page 46 with foreign slots page 55 Chapter 6 Foreign Types 48 foreign type alignment Syntax foreign type alignment type alignment Function Arguments and Values type A foreign type alignment An integer Description The function foreign type alignment returns the alignment of type in bytes
14. bitfield flags ctype flag a FLAG_A documentation DOCU_A flag b FLAG B FLAG B ALT documentation DOCU B flag c FLAG C documentation DOCU C optional t 13 3 ASDF Integration An example software project might contain four files an ASDF file a package definition file an implementation file and a CFFI Grovel specification file The ASDF file defines the system and its dependencies Notice the use of eval when to ensure CFFI Grovel is present and the use of cffi grovel grovel file name amp key cc flags instead of file name CFFI Grovel is needed for processing grovel file components cl eval when load toplevel execute asdf operate asdf load op cffi grovel asdf defsystem example software depends on cffi serial t components file package cffi grovel grovel file example grovelling file example Chapter 13 The Groveller 117 The package lisp file would contain several defpackage forms to remove circular de pendencies and make building the project easier Note that you may or may not want to use your internal package Implementor s note Mention that it s a not a good idea to USE when names may clash with say CL symbols defpackage example internal use nicknames exampleint defpackage example software export use cl cffi exampleint The internal package is created by Lisp code output from the C program
15. char but does not expect anything about the data there However it does expect that some libcurl function we call later can write a C string of up to 255 characters there We the callers of the function are expected to read the C string at a later time exactly the opposite of what string implies With the semantics for an input string in mind namely that the string should be kept around until we curl easy cleanup the easy handle we are ready to extend the Lisp interface defvar easy handle cstrings make hash table Hashtable of easy handles to lists of C strings that may be safely freed after the handle is freed defun make easy handle Answer a new CURL easy interface handle to which the lifetime of C strings may be tied See add curl handle cstring let easy handle curl easy init setf gethash easy handle easy handle cstrings easy handle defun free easy handle handle T But I thought Lisp was supposed to protect me from all that buggy C crap Before asking a question like that remember that you are a stranger in a foreign land whose residents have a completely different set of values Chapter 4 An Introduction to Foreign Interfaces and CFFI 14 Free CURL easy interface HANDLE and any C strings created to be its options curl easy cleanup handle mapc foreign string free gethash handle easy handle cstrings remhash handle easy handle cstrings de
16. curl option nosignal curl option nosignal long Chapter 4 An Introduction to Foreign Interfaces and CFFI 12 define curl option setter set curl option errorbuffer curl option errorbuffer pointer define curl option setter set curl option url curl option url pointer curl option Macroexpanding one of the new define curl option setter forms yields the following progn defcfun curl_easy_setopt set curl option nosignal curl code easy handle easy handle option curl option new value long curry curl option setter set curl option nosignal nosignal Finally let s try this out CFFI USER gt set curl option nosignal easy handle 1 gt 0 Looks like it works just as well This interface is now reasonably high level to wash out some of the ugliness of the thinnest possible curl_easy_setopt FFI without obscuring the remaining C bookkeeping details we will explore 4 8 Memory management According to the documentation for curl_easy_setopt the type of the third argument when option is CURLOPT_ERRORBUFFER is char Above we ve defined set curl option errorbuffer to accept a pointer as the new option value However there is a CFFI type string which translates Lisp strings to C strings when passed as arguments to foreign function calls Why not then use string as the CFFI type of the third argument There are two reasons both related to the necessity of breaking abstraction described in Section 4 6 Break
17. foreign string alloc page 78 foreign string to lisp page 80 lisp string to foreign page 81 with foreign string page 82 with foreign pointer as string page 83 Chapter 8 Strings 78 foreign string alloc Syntax foreign string alloc string amp key encoding Function null terminated p start end pointer Arguments and Values string A Lisp string encoding Foreign encoding Defaults to default foreign encoding null terminated p Boolean defaults to true start end Bounding index designators of string 0 and nil by default pointer A pointer to the newly allocated foreign string Description The foreign string alloc function allocates foreign memory holding a copy of string converted using the specified encoding Start specifies an offset into string and end marks the position following the last element of the foreign string This string must be freed with foreign string free If null terminated p is false the string will not be null terminated Examples CFFI gt defparameter str foreign string alloc Hello foreign world lt FOREIGN ADDRESS x00400560 gt CFFI gt foreign funcall strlen pointer str int 21 See Also foreign string free page 79 with foreign string page 82 Chapter 8 Strings 79 foreign string free Syntax foreign string free pointer Function Arguments and Values pointer A pointer to a string allocated by foreign string alloc Description
18. inc pointer page 63 null pointer page 69 null pointer p page 70 pointerp page 71 pointer address page 72 pointer eq page 73 mem ref page 68 65 Function Chapter 7 Pointers 66 mem aptr Syntax mem aptr ptr type amp optional index 0 Accessor Arguments and Values ptr A foreign pointer type A foreign type index An integer new value A Lisp value compatible with type Description The mem aptr function finds the pointer to an element of the array mem aptr ptr type n is identical to inc pointer ptr n foreign type size type Examples CFFI gt with foreign string str Hello foreign world mem aptr str char 6 SB SYS INT SAP X0063D4B6 Chapter 7 Pointers 67 mem aref Syntax mem aref ptr type amp optional index 0 Accessor setf mem aref ptr type amp optional index 0 new value Arguments and Values ptr A foreign pointer type A foreign type index An integer new value A Lisp value compatible with type Description The mem aref function is similar to mem ref but will automatically calculate the offset from an index mem aref ptr type n is identical to mem ref ptr type n foreign type size type Examples CFFI gt with foreign string str Hello foreign world mem aref str char 6 gt 32 CFFI gt code char gt Space CFFI gt with foreign object array int 10 loop for i below 10 do setf m
19. information about types and structures so you don t have to This is especially important for libraries which are implemented in different ways by different vendors such as the UNIX POSIX functions The CFFI declarations are usually quite different from platform to platform but the information you give to CFFI Grovel is the same Hence much less work is required If you use ASDF CFFI Grovel is integrated so that it will run automatically when your system is building This feature was inspired by SB Grovel a similar SBCL specific project CFFI Grovel can also be used without ASDF 13 1 Building FFIs with CFFI Grovel CFFI Grovel uses a specification file lisp describing the features that need groveling The C compiler is used to retrieve this data and write a Lisp file cffi lisp which contains the necessary CFFI definitions to access the variables structures constants and enums mentioned in the specification CFFI Grovel provides an ASDF component for handling the necessary calls to the C compiler and resulting file management 13 2 Specification File Syntax The specification files are read by the normal Lisp reader so they have syntax very similar to normal Lisp code In particular semicolon comments and reader macros will work as expected There are several forms recognized by CFFI Grovel progn amp rest forms Grovel Form Processes a list of forms Useful for conditionalizing several forms For example freebsd
20. on functions with a void return type is still undefined Implementation specific Notes e Corman Lisp does not support foreign funcall On implementations that don t support foreign funcall cffi sys no foreign funcall will be present in features Note in these Lisps you can still use the defcfun interface Examples CFFI gt foreign funcall pointer foreign symbol pointer abs int 42 int 42 See Also defcfun page 89 foreign funcall page 91 Chapter 10 Functions 94 translate camelcase name Syntax translate camelcase name name amp key upper initial p Function Special words return value Arguments and Values name Either a symbol or a string upper initial p A generalized boolean special words A list of strings return value If name is a symbol this is a string and vice versa Description translate camelcase name is a helper function for specializations of translate name from foreign and translate name to foreign It handles the common case of convert ing between foreign camelCase names and lisp names upper initial p indicates whether the first letter of the foreign name should be uppercase special words is a list of strings that should be treated atomically in translation This list is case sensitive Examples CFFI gt translate camelcase name some xml function gt someXmlFunction CFFI gt translate camelcase name some xml function upper initial p t gt SomeXmlF
21. repe qu ees 63 incf pointer place amp optional offset 1 gt new pointer i e eter rp Lb tr 64 J cludes ioie data re eret bebes dure aee 114 122 L library foreign bentesetreREUTPPUO TE T EE 6 limitations of type translators 20 lisp string to foreign string buffer bufsize amp key start end offset encoding buffer TEE 81 Lispy C functions 0 000008 10 load foreign library library designator Library 105 load foreign library error 107 loading CRRT sense se 5 looks like it worked 0 00000 7 M make pointer address gt ptr 65 mem aptr ptr type amp optional index 0 66 mem aref ptr type amp optional index 0 67 mem ref ptr type amp optional offset object icu er No Eq dde 68 minimal bindings cece eee eee 4 N null pointer pointer 69 null pointer p ptr boolean 70 P il LET 4 pkg config cflags 0 cece eee ee 115 pointer address ptr address 12 pointer eq ptri ptr2 boolean 73 pointerp ptr boolean sss T1 pointers in Tas T premature deallocation 2222222 12 PEOST isre em ewe kid pana shee uites Ee Eau dau 114 Python sia tie essen Egeria ERI 4 R requiring OFFL sereus ne i anwer stew adage 5 S SLIME 2 nLesntreersuieb ee a eat 4 Streams and CO
22. t work with every implementation of the C stan dard library Chapter 9 Variables See Also get var pointer page 87 86 Chapter 9 Variables 87 get var pointer Syntax get var pointer symbol pointer Function Arguments and Values symbol A symbol denoting a foreign variable defined with defcvar pointer A foreign pointer Description The function get var pointer will return a pointer to the foreign global variable symbol previously defined with defcvar Examples CFFI gt defcvar errno int read only t gt ERRNO CFFI gt errno gt 25 CFFI gt get var pointer errno lt A Mac Pointer xA0008130 gt CFFI gt mem ref int gt 25 See Also defcvar page 85 Chapter 10 Functions 10 Functions 88 Chapter 10 Functions 89 defcfun Syntax defcfun name and options return type amp body docstring Macro arguments amp rest lisp name name and options name name amp key library convention name lisp name foreign name foreign name lisp name arguments arg name arg type Arguments and Values foreign name A string denoting a foreign function lisp name A symbol naming the Lisp function to be created arg name A symbol return type arg type A foreign type convention One of cdecl default or stdcall library A symbol designating a foreign library docstring A documentation string Description The defcfun macro prov
23. to always load a separate Lisp or FASL file containing your expand definitions before compiling files with forms that ought to use them Otherwise they will not be found and the runtime translators will be used instead Chapter 6 Foreign Types 28 6 6 Foreign Structure Types For more involved C types than simple aliases to built in types such as you can make with defctype CFFI allows declaration of structures and unions with defcstruct and defcunion For example consider this fictional C structure declaration holding some personal infor mation struct person int number char reason 3 The equivalent defcstruct form follows defcstruct person number int reason string By default convert from foreign page 29 and also mem ref page 68 will make a plist with slot names as keys and convert to foreign page 30 will translate such a plist to a foreign structure A user wishing to define other translations should use the class argument to defcstruct page 33 and then define methods for translate from foreign page 52 and translate into foreign memory page 54 that specialize on this class possibly calling call next method to translate from and to the plists rather than provide a direct interface to the foreign object The macro translation forms for class will generate the forms necessary to translate a Lisp class into a foreign structure and vice versa Please note that this interface is only for those t
24. var or vars string amp rest args amp body body 000 82 with foreign strings bindings amp body body Bun el EESE en An re x dada pubis 82
25. written by CFFI Grovel if your specification file is exampleint lisp the exampleint cffi lisp file will contain the CFFI definitions needed by the rest of your project See Section 13 2 Groveller Syntax page 114 13 4 Implementation Notes Implementor s note This info might not be up to date For foo internal lisp the resulting foo internal c foo internal and foo internal cffi lisp are all platform specific either because of possible reader macros in foo internal lisp or because of varying C environments on the host system For this reason it is not helpful to distribute any of those files end users building CFFI Grovel based software will need cffi Grovel anyway If you build with multiple architectures in the same directory e g with NFS AFS home directories it is critical to remove these generated files or the resulting constants will be very incorrect Implementor s note Maybe we should tag the generated names with something host or OS specific Implementor s note For now after some experimentation with CLISP having no long long it seems appropriate to assert that the generated c files are architecture and operating system dependent but lisp implementation independent This way the same c file and so the same grovel tmp lisp file will be shareable between the implementations running on a given system Chapter 14 Limitations 118 14 Limitations These are CFFT s limitations across all platforms for informat
26. 0 CFFI gt foreign slot offset struct timeval tv usecs gt 4 See Also defestruct page 33 foreign slot names page 44 foreign slot pointer page 46 foreign slot value page 47 Chapter 6 Foreign Types 46 foreign slot pointer Syntax foreign slot pointer ptr type slot name pointer Function Arguments and Values ptr A pointer to a structure type A foreign structure type slot names A slot name in the type pointer A pointer to the slot slot name Description Returns a pointer to the location of the slot slot name in a foreign object of type type at ptr The returned pointer points inside the structure Both the pointer and the memory it points to have the same extent as ptr For aggregate slots this is the same value returned by foreign slot value Examples defcstruct point Pointer structure x int y int CFFI gt with foreign object ptr struct point foreign slot pointer ptr struct point x lt FOREIGN ADDRESS xBFFF6E60 gt Note the exact pointer representation varies from lisp to lisp See Also defestruct page 33 foreign slot value page 47 foreign slot names page 44 foreign slot offset page 45 Chapter 6 Foreign Types 4T foreign slot value Syntax foreign slot value ptr type slot name object Accessor Arguments and Values ptr A pointer to a structure type A foreign structure type slot name A symbol naming
27. 2 Callbacks page 109 will not be available 32 bit Lispworks 5 0 is an exception In addition to the CFFI implementation described above Lispworks itself implements the long long type for Chapter 10 Functions page 88 Chapter 12 Callbacks page 109 are still missing long long support though cffi sys no stdcall This Lisp doesn t support the stdcall calling convention Note that it only makes sense to support stdcall on 32 bit x86 platforms Appendix B Glossary 120 Appendix B Glossary aggregate type A CFFI type for C data defined as an organization of data of simple type in structures and unions which are themselves aggregate types they are repre sented by value foreign value This has two meanings in any context only one makes sense When using type translators the foreign value is the lower level Lisp value derived from the object passed to translate to foreign see translate to foreign page 53 This value should be a Lisp number or a pointer satisfies pointerp and it can be treated like any general Lisp object it only completes the transformation to a true foreign value when passed through low level code in the Lisp implementation such as the foreign function caller or indirect memory addressing combined with a data move In other contexts this refers to a value accessible by C but which may only be accessed through CFFI functions The closest you can get to such a foreign value is through a pointer
28. CFFI User Manual Copyright 2005 James Bielman lt jamesjb at jamesjb com gt Copyright 2005 2015 Luis Oliveira lt loliveira at common lisp net gt Copyright 2005 2006 Dan Knapp lt danka at accela net gt Copyright 2005 2006 Emily Backes lt lucca at accela net gt Copyright 2006 Stephen Compall s11 at member fsf org gt Permission is hereby granted free of charge to any person obtaining a copy of this software and associated documentation files the Software to deal in the Software without restriction including without limitation the rights to use copy modify merge publish distribute sublicense and or sell copies of the Software and to permit persons to whom the Software is furnished to do so subject to the following conditions The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software THE SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND EX PRESS OR IMPLIED INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MER CHANTABILITY FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM DAMAGES OR OTHER LIABILITY WHETHER IN AN ACTION OF CONTRACT TORT OR OTHERWISE ARISING FROM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE Table of Contents 1 I lroduchioH 222 cra DERECHA COR 1 2 Installation so e ERR RR REX
29. Chapter 6 Foreign Types 35 defcunion Syntax defcunion name amp body doc and slots name Macro doc and slots docstring slot name slot type amp key count Arguments and Values name The name of new union type docstring A documentation string ignored slot name A symbol naming the slot slot type The type specifier for the slot count Used to declare an array of size count inside the structure Description A union is a structure in which all slots have an offset of zero It is isomorphic to the C union Therefore you should use the usual foreign structure operations for accessing a union s slots Examples defcunion uint32 bytes int value unsigned int bytes unsigned char count 4 See Also foreign slot pointer page 46 foreign slot value page 47 Chapter 6 Foreign Types defctype Syntax defctype name base type amp optional documentation Arguments and Values name The name of the new foreign type base type A symbol or a list defining the new type documentation A documentation string currently ignored Description 36 Macro The defctype macro provides a mechanism similar to C s typedef to define new types The new type inherits base type s translators if any There is no way to define translations for types defined with defctype For that you should use define foreign type page 38 Examples defctype my string string My own string type defct
30. If octet size var is provided it will be bound the length of foreign string in octets in cluding the null terminator Examples CFFI gt with foreign string foo 12345 foreign funcall strlen pointer foo int gt 5 CFFI gt let array coerce 84 117 114 97 110 103 97 array unsigned byte 8 with foreign string foreign string array foreign string to lisp foreign string Turanga See Also foreign string alloc page 78 with foreign pointer as string page 83 Chapter 8 Strings 83 with foreign pointer as string Syntax with foreign pointer as string var size amp optional size var Macro amp rest args amp body body string Arguments and Values var A symbol string A Lisp string body List of forms to be executed Description The with foreign pointer as string macro is similar to with foreign pointer ex cept that var is used as the returned value of an implicit progn around body after being converted to a Lisp string using the provided args Examples CFFI gt with foreign pointer as string str 6 str size encoding ascii lisp string to foreign Hello foreign world str str size gt Hello See Also foreign string alloc page 78 with foreign string page 82 Chapter 9 Variables 9 Variables 84 Chapter 9 Variables 85 defcvar Syntax defcvar name and options type amp optional documentation gt Macro lisp name name and options name
31. Lisp object which itself counts as a foreign value in only the previous sense simple type A CFFI type that is ultimately represented as a builtin type CFFI only provides extra semantics for Lisp that are invisible to C code or data Index DOOD rain sigue cena dine Ga ean ete cathe eed 24 boolean amp optional base type int 24 CHarllilldleddefspsrcevecesene tur buda ae 22 double eatin ik sauna ot oa EDS 23 PLOAt Sind ornate dean peso ghi scd EGRE equus 23 int ollibsubldfrRen sei ade ed reo una d media 22 Dag crc a 22 int32 ils E E e db ber ietter us 22 iHt64 es nenn 23 pb ies chido e eats C UPS REA MESS AE 22 llongu nc neu an fiie e nennen 22 MONG esis seating ang sa dan Le RE RUE a 22 long dou ble si ene heec edes sedes 23 Slong long ie ssi gag handed sae aioe esa ERE 22 pointer amp optional type 23 A oh o sn a ana 22 SUEIDB det een ei 23 StLINEFPEr aan 23 ai ad o Te EE EE E rauen 22 USE 2122 ee une 22 pabuli ee 22 WINGS o DIL en ee 22 MINT 64 een ae ee deren 23 USED eree ee iS 22 ULlOng m 22 WONG nennen 22 nsigned char iiic da rec d n dave 22 unsigned int sauna e piede add 22 unsigned long 0 cece eee eee eee 22 unsigned long long sess 22 unsigned Shorter iarere tantn nii ranis 22 an ato i a zu ana 22 bidon Ko M E E EELEE EE EAEE 23 wrapper base type amp key to c from c 24 A abstraction breaking
32. We could make cl defun forms in the expansion that simply call curl easy setopt however it is probably easier and clearer to use defcfun define curl options was becoming unwieldy so I defined some helpers in this new definition defun curry curl option setter function name option keyword Wrap the function named by FUNCTION NAME with a version that curries the second argument as OPTION KEYWORD This function is intended for use in DEFINE CURL OPTION SETTER setf symbol function function name let c function symbol function function name lambda easy handle new value funcall c function easy handle option keyword new value defmacro define curl option setter name option type option value foreign type Define with DEFCFUN a function NAME that calls curl_easy_setopt OPTION TYPE and OPTION VALUE are the CFFI foreign type and value to be passed as the second argument to easy_setopt and FOREIGN TYPE is the CFFI foreign type to be used for the resultant function s third argument This macro is intended for use in DEFINE CURL OPTIONS progn defcfun curl easy setopt name curl code Chapter 4 An Introduction to Foreign Interfaces and CFFI 11 easy handle easy handle option option type new value foreign type curry curl option setter name option value defmacro define curl options type name type offsets amp rest enum args As with CFFI DEFCENUM except each of ENUM ARGS is as foll
33. alue type keyword amp key errorp Valle een 43 foreign free ptr undefined 59 foreign funcall name and options amp rest arguments return value 91 foreign funcall pointer pointer options amp rest arguments return value 93 foreign pointer serisss gue e Da diu eg 57 foreign slot names type names 44 foreign slot offset type slot name offset DUO 45 foreign slot pointer ptr type slot name podnter icceficasupeeesemrti ectvesspexeg er 46 foreign slot value ptr type slot name Caco rm 4T foreign string alloc string amp key encoding null terminated p start end pointer xpi dier uoi ade EPEE ten 78 foreign string free pointer 79 foreign string to lisp ptr amp key offset count max chars encoding string 80 foreign symbol pointer foreign name amp key library gt pointer sss 62 foreign type alignment type alignment 48 foreign type size type size 49 free converted object foreign value type Darams 2 feet eceecn ten Shaded Sted eee 50 free translated object value type name param ade 51 function definition 0 0006 6 G get callback symbol pointer 113 get var pointer symbol pointer 8T I in package cie dep ien eps ended 114 inc pointer pointer offset new pointer CUIR Penn EPI ead Tete
34. an and can t do and why this is so 4 6 Breaking the abstraction In Section 4 1 What makes Lisp different page 4 we mentioned that writing an FFI sometimes requires depending on information not provided as part of the interface The easy option CURLOPT_WRITEDATA which we will not provide as part of the Lisp interface illustrates this issue Strictly speaking the curl option enumeration is not necessary we could have used int 99 instead of curl option nosignal in our call to curl_easy_setopt above We defined it anyway in part to hide the fact that we are breaking the abstraction that the C enum provides If the cURL developers decide to change those numbers later we must change the Lisp enumeration because enumeration values are not provided in the compiled C library libcurl so 3 CFFI works because the most useful things in C libraries non static functions and non static variables are included accessibly in libcurl so 3 A C compiler that violated this would be considered a worthless compiler The other thing define curl options does is give the type of the third argument passed to curl_easy_setopt Using this information we can tell that the nosignal option should accept a long integer argument We can implicitly assume t 1 and nil 0 as it is in C which takes care of the fact that CURLOPT_NOSIGNAL is really asking for a boolean The type of CURLOPT_WRITEDATA is objectpoint However it is really
35. and set its URL CFFI USER gt curl easy cleanup easy handle NIL CFFI USER gt setf easy handle make easy handle lt FOREIGN ADDRESS x09844EE0 gt CFFI USER gt set curl option nosignal easy handle 1 gt 0 CFFI USER gt set curl option url easy handle http www cliki net CFFI gt 0 8 There are advantages and disadvantages to each approach I chose to setf symbol function earlier because it entailed generating fewer magic function names Chapter 4 An Introduction to Foreign Interfaces and CFFI 15 For fun let s inspect the Lisp value of the C string that was created to hold http www cliki net CFFI By virtue of the implementation of add curl handle cstring it should be accessible through the hash table defined CFFI USER gt foreign string to lisp car gethash easy handle easy handle cstrings gt http www cliki net CFFI Looks like that worked and libcurl now knows what URL we want to retrieve Finally we turn back to the errorbuffer option mentioned at the beginning of this section Whereas the abstraction added to support string inputs works fine for cases like CURLOPT_URL it hides the detail of keeping the C string for errorbuffer however we need that C string In a moment we ll define something slightly cleaner but for now remember that you can always hack around anything We re modifying handle creation so make sure you free the old handle before re
36. at to work Description This is an external interface to the type translation facility In the implementation all for eign functions are ultimately defined as type translation wrappers around primitive foreign function invocations This function is available mostly for inspection of the type translation process and possibly optimization of special cases of your foreign function calls Its behavior is better described under translate to foreign s documentation Examples CFFI USER gt convert to foreign t boolean gt 1 NIL CFFI USER gt convert to foreign hello world string lt FOREIGN ADDRESS x097C5F80 gt T CFFI USER gt code char mem aref char 5 gt See Also convert from foreign page 29 free converted object page 50 translate to foreign page 53 Chapter 6 Foreign Types 31 defbitfield Syntax defbitfield name and options amp body masks Macro masks docstring symbol value name and options name name amp optional base type int Arguments and Values name The name of the new bitfield type docstring A documentation string ignored base type A symbol denoting a foreign type symbol A Lisp symbol value An integer representing a bitmask Description The defbitfield macro is used to define foreign types that map lists of symbols to integer values If value is omitted it will be computed as follows find the greatest value previously us
37. ating Foreign Memory ssssssseses e 57 7 3 Accessing Foreign Memory sss od B SL EINE te Ka AREA 76 D Variables vex cd Rei ERE REA kde ten ee ES 84 l0 Functions ses near a 88 Il dabrafieS4 4 ebbe b PD een 98 11 1 Defining library eee eee ea 98 11 2 Library definition style 2 0 98 12 Calibachs ocseectedshawnteda ancy seen ar 109 13 The Groveller 0 0005 114 13 1 Building FFIs with CFFI Grovel sseeeeeeeees 114 13 2 Specification File Syntax 0 0 cece eee eee 114 13 3 ASDF Integration ssseeseeeeees e ne 116 13 4 Implementation Notes 00 e eee eee eee eee eee 117 14 Limitations se eee 118 Appendix A Platform specific features 119 Appendix B Glossary 120 Chapter 1 Introduction 1 1 Introduction CFFI is the Common Foreign Function Interface for ANSI Common Lisp systems By foreign function we mean a function written in another programming language and having different data and calling conventions than Common Lisp namely C CFFI allows you to call foreign functions and access foreign variables all without leaving the Lisp image We consider this manual ever a work in progress If you have difficulty with anything CFFI specific presented in the manual please contact the developers with details Motivation See Section 4 1 What makes Lisp different page 4 for an argume
38. be assured that you can just as easily add to the bindings if need be Chapter 4 An Introduction to Foreign Interfaces and CFFI 5 The removal of the C compiler or C interpretation of any kind creates the main disad vantage some of C s abstractions are not available violating information encapsulation For example structs that must be passed on the stack or used as return values without corresponding functional abstractions to create and manage the structs must be declared explicitly in Lisp This is fine for structs whose contents are public but is not so pleasant when a struct is supposed to be opaque by convention even though it is not so defined Without an abstraction to create the struct Lisp needs to be able to lay out the struct in memory so must know its internal details In these cases you can create a minimal C library to provide the missing abstractions without destroying all the advantages of the Common Lisp approach discussed above In the case of structs you can write simple pure C functions that tell you how many bytes a struct requires or allocate new structs read and write fields of the struct or whatever operations are supposed to be public Chapter 13 The Groveller page 114 automates this and other processes Another disadvantage appears when you would rather use the foreign language than Lisp However someone who prefers C to Lisp is not a likely candidate for developing a Lisp int
39. bol naming the new foreign type lambda list A lambda list which is the argument list of the new foreign type body One or more forms that provide a definition of the new foreign type Description Examples Taken from CFFT s boolean type definition define foreign type boolean amp optional base type int Boolean type Maps to an int by default Only accepts integer types ecase base type char unsigned char int unsigned int long unsigned long base type CFFI gt canonicalize foreign type boolean gt INT CFFI gt canonicalize foreign type boolean long LONG CFFI gt canonicalize foreign type boolean float erro signalled by ECASE See Also define foreign type page 38 Chapter 6 Foreign Types AO foreign bitfield symbols Syntax foreign bitfield symbols type value gt symbols Function Arguments and Values type A bitfield type value An integer symbols A potentially shared list of symbols nil Description The function foreign bitfield symbols returns a possibly shared list of symbols that correspond to value in type Examples defbitfield flags flag a 1 flag b 2 flag c 4 CFFI gt foreign bitfield symbols boolean b101 FLAG A FLAG C See Also defbitfield page 31 foreign bitfield value page 41 Chapter 6 Foreign Types Al foreign bitfield value Syntax foreign bitfield value type symbols value Fun
40. by CFFI have a reasonable default search algorithm for foreign libraries For example Lisps for UNIX usually call dlopen 3 which in turn looks in the system library directories Only if that fails does CFFI look for the named library file in these directories and load it from there if found Thus this is intended to be a CFFI only fallback to the library search configuration provided by your operating system For example if you distribute a foreign library with your Lisp package you can add the library s containing directory to this list and portably expect CFFI to find it A simple Lisp expression is intended to provide functionality commonly used in search paths such as ASDF s and is defined recursively as follows 1 A list whose first is a function designator and whose rest is a list of simple Lisp expressions to be evaluated and passed to the so designated function The result is the result of the function call 2 A symbol whose result is its symbol value 3 Anything else evaluates to itself The result of evaluating the simple Lisp expression should yield a designator for a list of pathname designators Note in Common Lisp p foo bar designates the bar file within the foo direc tory whereas p foo bar designates the foo bar directory Keep that in mind when customising the value of foreign library directories Examples 1s 4 liblibli so libli lisp In libli lisp 1 See Section
41. ction Arguments and Values type A bitfield type symbol A Lisp symbol value An integer Description The function foreign bitfield value returns the value that corresponds to the symbols in the symbols list Examples defbitfield flags flag a 1 flag b 2 flag c 4 CFFI gt foreign bitfield value flags flag a flag c 5 b101 See Also defbitfield page 31 foreign bitfield symbols page 40 Chapter 6 Foreign Types 42 foreign enum key word Syntax foreign enum keyword type value amp key errorp keyword Function Arguments and Values type An enum type value An integer errorp If true the default signal an error if value is not defined in type If false foreign enum keyword returns nil keyword A keyword symbol Description The function foreign enum keyword returns the keyword symbol that corresponds to value in type An error is signaled if type doesn t contain such value and errorp is true Examples defcenum boolean no yes CFFI gt foreign enum keyword boolean 1 gt YES See Also defcenum page 37 foreign enum value page 43 Chapter 6 Foreign Types 43 foreign enum value Syntax foreign enum value type keyword amp key errorp value Function Arguments and Values type An enum type keyword A keyword symbol errorp If true the default signal an error if keyword is not defined in type If false foreign enum value retur
42. ctions that interest you Wrapper generators should be treated as time savers not complete automation of the full foreign interface writing job Reports of the amount of work done by generators vary from 30 to 90 The incremental development style enabled by CFFI generally reduces this proportion below that for languages like Python Chapter 6 Foreign Types 6 Foreign Types 22 Foreign types describe how data is translated back and forth between C and Lisp CFFI provides various built in types and allows the user to define new types 6 1 Built In Types char unsigned char short unsigned short int unsigned int long unsigned long long long unsigned long long Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type These types correspond to the native C integer types according to the ABI of the Lisp implementation s host system long long and unsigned long long are not supported natively on all implementa tions However they are emulated by mem ref and mem set When those types are not available the symbol cffi sys no long long is pushed into features uchar ushort uint ulong llong ullong Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type For convenience the above types are provided as shortcuts for unsigned char unsigned short unsigned int unsig
43. d foreign name doesn t exist nil is returned ABI name manglings will be performed on foreign name by foreign symbol pointer if necessary eg adding a leading underscore on darwin ppc library should name a foreign library as defined by define foreign library default which is the default or an instance of foreign library as returned by load foreign library Important note do not keep these pointers across saved Lisp cores as the foreign library may move across sessions Examples CFFI gt foreign symbol pointer errno lt A Mac Pointer xA0008130 gt CFFI gt foreign symbol pointer strerror lt A Mac Pointer x9002D0F8 gt CFFI gt foreign funcall pointer int mem ref int string No such file or directory CFFI gt foreign symbol pointer inexistent symbol NIL See Also defcvar page 85 Chapter 7 Pointers inc pointer Syntax inc pointer pointer offset gt new pointer Arguments and Values pointer new pointer A foreign pointer offset An integer Description 63 Function The function inc pointer will return a new pointer pointing offset bytes past pointer Examples CFFI gt foreign string alloc Common Lisp lt A Mac Pointer x102EA0 gt CFFI gt inc pointer 7 lt A Mac Pointer x102EA7 gt CFFI gt foreign string to lisp gt Lisp See Also incf pointer page 64 make pointer page 65 pointerp page 71 null pointer
44. de alloc param If present this value will be passed to free translated object Description This generic function is invoked by CFFI to convert a Lisp value to a foreign value such as when passing arguments to a foreign function returning a value from a callback or setting a foreign variable A foreign value is one appropriate for passing to the next lowest translator including the low level translators that are ultimately invoked invisibly with CFFI To extend the CFFI type system by performing custom translations this method may be specialized by EQL specializing type name on a symbol naming a foreign type defined with defctype This method should return the appropriate foreign value to use in place of the Lisp value In cases where CFFI can determine the lifetime of the foreign object returned by this method it will invoke free translated object on the foreign object at the appropriate time If translate to foreign returns a second value it will be passed as the param argu ment to free translated object This can be used to establish communication between the allocation and deallocation methods The results are undefined if the type name parameter is specialized in any way except an EQL specializer on a foreign type defined with defctype Specifically translations may not be defined for built in types See Also Section 6 4 Foreign Type Translators page 25 translate from foreign page 52 free translated object pag
45. defcfun rand int CFFI gt rand 1804289383 Variadic function example defcfun sprintf int str pointer control string amp rest CFFI gt with foreign pointer as string s 100 sprintf s Ac d 4 2f s char 90 short 42 string super locrian gt A 42 3 14 super locrian See Also foreign funcall page 91 foreign funcall pointer page 93 float pi 90 Chapter 10 Functions 91 foreign funcall Syntax foreign funcall name and options amp rest arguments Macro return value arguments arg type arg return type name and options name name amp key library convention Arguments and Values name A Lisp string arg type A foreign type arg An argument of type arg type return type A foreign type void by default return value A lisp object library A lisp symbol not evaluated convention One of cdecl default or stdcall Description The foreign funcall macro is the main primitive for calling foreign functions If a foreign structure is to be passed or returned by value that is the type is of the form struct then the cffi libffi system must be loaded which in turn depends on libffi including the header files Failure to load that system will result in an error Variadic functions cannot at present accept or return structures by value Note The return value of foreign funcall on functions with a void return type is still undefined Imp
46. defining free easy handle defvar easy handle errorbuffers make hash table Hashtable of easy handles to C strings serving as error writeback buffers An extra byte is very little to pay for peace of mind defparameter curl error size 257 Minimum char size used by cURL to report errors defun make easy handle Answer a new CURL easy interface handle to which the lifetime of C strings may be tied See add curl handle cstring let easy handle curl easy init setf gethash easy handle easy handle cstrings setf gethash easy handle easy handle errorbuffers foreign alloc char count curl error size initial element 0 easy handle defun free easy handle handle Free CURL easy interface HANDLE and any C strings created to be its options curl easy cleanup handle foreign free gethash handle easy handle errorbuffers remhash handle easy handle errorbuffers mapc foreign string free gethash handle easy handle cstrings remhash handle easy handle cstrings defun get easy handle error handle Answer a string containing HANDLE s current error message foreign string to lisp gethash handle easy handle errorbuffers Be sure to once again set the options we ve set thus far You may wish to define yet another wrapper function to do this 4 9 Calling Lisp from C If you have been reading curl_easy_setopt 3 you should have noticed that some
47. dify translation semantics based on other arguments to a function call In these cases you should rely on other features of Lisp rather than the powerful yet domain specific type translator interface 4 12 What s next CFFI provides a rich and powerful foundation for communicating with foreign libraries as we have seen it is up to you to make that experience a pleasantly Lispy one This tutorial does not cover all the features of CFFI please see the rest of the manual for details In particular if something seems obviously missing it is likely that either code or a good reason for lack of code is already present Implementor s note There are some other things in CFFI that might deserve tutorial sections such as free translated object or structs Let us know which ones you care about Chapter 5 Wrapper generators 21 5 Wrapper generators CFFI s interface is designed for human programmers being aimed at aesthetic as well as technical sophistication However there are a few programs aimed at translating C and C header files or approximations thereof into CFFI forms constituting a foreign interface to the symbols in those files These wrapper generators are known to support output of CFFI forms Verrazano Designed specifically for Common Lisp Uses GCC s parser output in XML format to discover functions variables and other header file data This means you need GCC to generate forms on the other hand the parser empl
48. e CFFI gt eql null pointer null pointer NIL CFFI gt pointer eq null pointer null pointer T See Also inc pointer page 63 Chapter 7 Pointers 74 with foreign object with foreign objects Syntax with foreign object var type amp optional count amp body body Macro with foreign objects bindings amp body body Macro bindings var type amp optional count Arguments and Values var A symbol type A foreign type evaluated count An integer Description The macros with foreign object and with foreign objects bind var to a pointer to count newly allocated objects of type type during body The buffer has dynamic extent and may be stack allocated if supported by the host Lisp Examples CFFI gt with foreign object array int 10 dotimes i 10 setf mem aref array int i random 100 loop for i below 10 collect mem aref array int i gt 22 7 22 52 69 1 46 93 90 65 See Also foreign alloc page 60 Chapter 7 Pointers 75 with foreign pointer Syntax with foreign pointer var size amp optional size var amp body Macro body Arguments and Values var size var A symbol size An integer body A list of forms to be executed Description The with foreign pointer macro binds var to size bytes of foreign memory during body The pointer in var is invalid beyond the dynamic extend of body and may be stack allocated if supported by the implementation If si
49. e 51 Chapter 6 Foreign Types 54 translate into foreign memory Syntax translate into foreign memory lisp value type name Generic Function pointer Arguments and Values lisp value The Lisp value to convert to foreign representation type name A symbol or list struct structure name naming a foreign type defined by defctype pointer The foreign pointer where the translated object should be stored Description Translate the Lisp value into the foreign memory location given by pointer The return value is not used Chapter 6 Foreign Types 55 with foreign slots Syntax with foreign slots vars ptr type amp body body Macro Arguments and Values vars A list with each element a symbol or list of length two with the first element pointer and the second a symbol ptr A foreign pointer to a structure type A structure type body A list of forms to be executed Description The with foreign slots macro creates local symbol macros for each var in vars to ref erence foreign slots in ptr of type If the var is a list starting with pointer it will bind the pointer to the slot rather than the value It is similar to Common Lisp s with slots macro Examples defcstruct tm sec int min int hour int mday int mon int year int wday int yday int isdst boolean zone string gmtoff long CFFI gt with foreign object time int setf mem ref time int foreign funcal
50. ed including those so computed with only a single 1 bit in its binary representation that is powers of two and left shift it by one This rule guarantees that a computed value cannot clash with previous values but may clash with future explicitly specified values Symbol lists will be automatically converted to values and vice versa when being passed as arguments to or returned from foreign functions respectively The same applies to any other situations where an object of a bitfield type is expected Types defined with defbitfield canonicalize to base type which is int by default Examples defbitfield open flags rdonly x0000 wronly x0001 rdwr HE nonblock append creat x0200 etc CFFI gt foreign bitfield symbols open flags b1101 RDONLY WRONLY NONBLOCK APPEND CFFI gt foreign bitfield value open flags rdwr creat 514 x0202 defcfun open unix open int Chapter 6 Foreign Types path string flags open flags mode uint16 unportable CFFI gt unix open tmp foo wronly creat 0644 gt lt an fd gt Consider also the following lispier wrapper around open defun lispier open path mode amp rest flags unix open path flags mode See Also foreign bitfield value page 41 foreign bitfield symbols page 40 32 Chapter 6 Foreign Types 33 defcstruct Syntax defcstruct name and options amp body doc and slots name Macro na
51. efined by mem aref and mem ref Given a pointer and a CFFI type see Chapter 6 Foreign Types page 22 either of these will dereference the pointer translate the C data there back to Lisp and return the result of 1 The definition of memory includes the CPU registers Chapter 7 Pointers 58 said translation performing the reverse operation when setf ing To decide which one to use consider whether you would use the array index operator n or the pointer dereference in C use mem aref for array indexing and mem ref for pointer dereferencing Chapter 7 Pointers 59 foreign free Syntax foreign free ptr gt undefined Function Arguments and Values ptr A foreign pointer Description The foreign free function frees a ptr previously allocated by foreign alloc The con sequences of freeing a given pointer twice are undefined Examples CFFI gt foreign alloc int lt A Mac Pointer x1022E0 gt CFFI gt foreign free NIL See Also foreign alloc page 60 with foreign pointer page 75 Chapter 7 Pointers 60 foreign alloc Syntax foreign alloc type amp key initial element initial contents Function count 1 null terminated p pointer Arguments and Values type A foreign type initial element A Lisp object initial contents A sequence count An integer Defaults to 1 or the length of initial contents if supplied null terminated p A boolean false by default pointer A forei
52. em aref array int i random 100 loop for i below 10 collect mem aref array int i gt 22 7 22 52 69 1 46 93 90 65 Compatibility Note For compatibility with older versions of CFFI mem aref page 67 will produce a pointer for the deprecated bare structure specification but it is consistent with other types for the current specification form struct structure name and provides a Lisp object trans lated from the structure by default a plist In order to obtain the pointer you should use the new function mem aptr page 66 See Also mem ref page 68 mem aptr page 66 Chapter 7 Pointers 68 mem ref Syntax mem ref ptr type amp optional offset object Accessor Arguments and Values ptr A pointer type A foreign type offset An integer in byte units object The value ptr points to Description Examples CFFI gt with foreign string ptr Saluton setf mem ref ptr char 3 char code a loop for i from 0 below 8 collect code char mem ref ptr char i gt CAS a SNL a t o n Null CFFI gt setq ptr to int foreign alloc int lt A Mac Pointer x1047D0 gt CFFI gt mem ref ptr to int int 1054619 CFFI gt setf mem ref ptr to int int 1984 1984 CFFI gt mem ref ptr to int int 1984 See Also mem aref page 67 Chapter 7 Pointers null pointer Syntax null pointer pointer Arguments and Values pointer A NULL pointer Descri
53. eneral purpose macro foreign funcall to call this function To make things easier on ourselves we ll create an enumeration of the kinds of options we want to set The enum CURLoption isn t the most straightforward but reading the CINIT C macro definition should be enlightening defmacro define curl options name type offsets amp rest enum args As with CFFI DEFCENUM except each of ENUM ARGS is as follows NAME TYPE NUMBER Where the arguments are as they are with the CINIT macro defined in curl h except NAME is a keyword Chapter 4 An Introduction to Foreign Interfaces and CFFI 8 TYPE OFFSETS is a plist of TYPEs to their integer offsets as defined by the CURLOPTTYPE_LONG et al constants in curl h flet enumerated value type offset getf type offsets type offset progn defcenum name loop for name type number in enum args collect list name enumerated value type number gt name for REPL users sanity define curl options curl option long 0 objectpoint 10000 functionpoint 20000 off t 30000 noprogress long 43 nosignal long 99 errorbuffer objectpoint 10 url objectpoint 2 N 77 77 With some well placed Emacs query replace regexps you could probably similarly define the entire CURLoption enumeration I have selected to transcribe a few that we will use in this tutorial If you re having trouble following the macrology just macroexpand the curl option definition or see the
54. er invocation This syntax can be used instead of hard coding paths using cc flags and ensures that include flags are added correctly on the build system Assumes pkg config is installed and working pkg is a string that identifies an installed pkg config package See the pkg config manual for more information If optional is true failure to execute pkg config does not abort compilation cstruct lisp name c name slots Grovel Form Define a CFFI foreign struct with the slot data specfied Slots are of the form lisp name c name amp key type count signed t cunion lisp name c name slots Grovel Form Identical to cstruct but defines a CFFI foreign union cstruct and class c name slots Grovel Form Defines a CFFI foreign struct as with cstruct and defines a CLOS class to be used with it This is useful for mapping foreign structures to application layer code that shouldn t need to worry about memory allocation issues cvar namespec type amp key read only Grovel Form Defines a foreign variable of the specified type even if that variable is potentially a C preprocessor pseudo variable e g cvar errno errno errno values assum ing that errno values is an enum or equivalent to type int The namespec is similar to the one used in defcvar page 85 cenum name and opts amp rest elements Grovel Form Defines a true C enum with elements specified as lisp name amp rest c names amp key optional documentation name and o
55. erface to a C library 4 2 Getting a URL The widely available libcurl is a library for downloading files over protocols like HTTP We will use libcurl with CFFI to download a web page Please note that there are many other ways to download files from the web not least the CL CURL project to provide bindings to libcurl via a similar FFI libcurl tutorial 3 is a tutorial for libcurl programming in C We will follow that to develop a binding to download a file We will also use curl h easy h and the man pages for the libcurl function all available in the curl dev package or equivalent for your system or in the cURL source code package If you have the development package the headers should be installed in usr include curl and the man pages may be accessed through your favorite man facility 4 3 Loading foreign libraries First of all we will create a package to work in You can save these forms in a file or just send them to the listener as they are If creating bindings for an ASDF package of yours you will want to add cffi to the depends on list in your asd file Otherwise just use the asdf oos function to load CFFI 1 Admittedly this is an advanced issue and we encourage you to leave this text until you are more familiar with how CFFI works This does not apply to structs whose contents are intended to be part of the public library interface In those cases a pure Lisp struct definition i
56. fine foreign type Syntax define foreign type class name supers slots amp rest options gt Macro class name options actual type type simple parser symbol regular defclass option Arguments and Values class name A symbol naming the new foreign type class supers A list of symbols naming the super classes slots A list of slot definitions passed to defclass Description The macro define foreign type defines a new class class name It is a thin wrapper around defclass Among other things it ensures that class name becomes a subclass of foreign type what you need to know about that is that there s an initarg actual type which serves the same purpose as defctype s base type argument Examples Taken from CFFI s boolean type definition define foreign type boolean amp optional base type int Boolean type Maps to an int by default Only accepts integer types ecase base type C char unsigned char int unsigned int long unsigned long base type CFFI gt canonicalize foreign type boolean gt INT CFFI gt canonicalize foreign type boolean long LONG CFFI gt canonicalize foreign type boolean float 33 signalled by ECASE See Also defctype page 36 define parse method page 39 Chapter 6 Foreign Types 39 define parse method Syntax define parse method name lambda list amp body body gt name Macro Arguments and Values type name A sym
57. following macroexpansion conveniently downcased and reformatted progn defcenum curl option noprogress 43 nosignal 99 errorbuffer 10010 url 10002 curl option That seems more than reasonable You may notice that we only use the type to compute the real enumeration offset we will also need the type information later First however let s make sure a simple call to the foreign function works CFFI USER gt foreign funcall curl_easy_setopt pointer easy handle curl option nosignal long 1 curl code gt 0 foreign funcall despite its surface simplicity can be used to call any C function Its first argument is a string naming the function to be called Next for each argument we pass the name of the C type which is the same as in defcfun followed by a Lisp object representing the data to be passed as the argument The final argument is the return type for which we use the curl code type defined earlier defcfun just puts a convenient facade on foreign funcall Our earlier call to curl global init could have been written as follows 4 This isn t entirely true some Lisps don t support foreign funcall so defcfun is implemented without it defcfun may also perform optimizations that foreign funcall cannot Chapter 4 An Introduction to Foreign Interfaces and CFFI 9 CFFI USER gt foreign funcall curl_global_init long 0 curl code gt 0 Before we continue we will take a look at what CFFI c
58. foreign library directories page 103 In contrast to that variable this is not a fallback search path the default value described above is intended to be a reasonably complete search path on Darwin systems Examples CFFI gt let lib load foreign library framework OpenGL foreign library pathname lib gt P System Library Frameworks OpenGL framework OpenGL See also foreign library directories page 103 define foreign library page 101 Chapter 11 Libraries 101 define foreign library Syntax define foreign library name and options load clause gt Macro name name and options name name amp key convention search path load clause fea ture library amp key convention search path Arguments and Values name A symbol feature A feature expression library A library designator convention One of cdecl default or stdcall search path A path or list of paths where the library will be searched if not found in system global directories Paths specified in a load clause take priority over paths spec ified as library option with foreign library directories having lowest priority Description Creates a new library designator called name The load clauses describe how to load that designator when passed to load foreign library or use foreign library When trying to load the library name the relevant function searches the load clauses in order for the first one where feature e
59. fun add curl handle cstring handle cstring Add CSTRING to be freed when HANDLE is answering CSTRING car push cstring gethash handle easy handle cstrings Here we have redefined the interface to create and free handles to associate a list of allocated C strings with each handle while it exists The strategy of using different function names to wrap around simple foreign functions is more common than the solution implemented earlier with curry curl option setter which was to modify the function name s function slot Incidentally the next step is to redefine curry curl option setter to allocate C strings for the appropriate length of time given a Lisp string as the new value argument defun curry curl option setter function name option keyword Wrap the function named by FUNCTION NAME with a version that curries the second argument as OPTION KEYWORD This function is intended for use in DEFINE CURL OPTION SETTER setf symbol function function name let c function symbol function function name lambda easy handle new value funcall c function easy handle option keyword if stringp new value add curl handle cstring easy handle foreign string alloc new value new value A quick analysis of the code shows that you need only reevaluate the curl option enu meration definition to take advantage of these new semantics Now for good measure let s reallocate the handle with the new functions we just defined
60. g to lisp foreign funcall foo pointer g2021 pointer Again no generic function overhead Other details To short circuit expansion and use the translate functions instead simply call the next method Return its result in cases where your method cannot generate an appropriate replacement for it This analogous to the amp whole form mechanism compiler macros provide The expand methods have precedence over their translate counterparts and are guaranteed to be used in defcfun foreign funcall defcvar and defcallback If you define a method on each of the expand generic functions you are guaranteed to have full control over the expressions generated for type translation in these macros They may or may not be used in other CFFI operators that need to translate between Lisp and C data you may only assume that expand methods will probably only be called during Lisp compilation expand to foreign dyn has precedence over expand to foreign and is only used in defcfun and foreign funcall only making sense in those contexts Important note this set of generic functions is called at macroexpansion time Methods are defined when loaded or evaluated not compiled You are responsible for ensuring that your expand methods are defined when the foreign funcall or other forms that use them are compiled One way to do this is to put the method definitions earlier in the file and inside an appropriate eval when form another way is
61. gn pointer to the newly allocated memory Description The foreign alloc function allocates enough memory to hold count objects of type type and returns a pointer This memory must be explicitly freed using foreign free once it is no longer needed If initial element is supplied it is used to initialize the count objects the newly allocated memory holds If an initial contents sequence is supplied it must have a length less than or equal to count and each of its elements will be used to initialize the contents of the newly allocated memory If count is omitted and initial contents is specified it will default to length initial contents initial element and initial contents are mutually exclusive When null terminated p is true 1 max count length initial contents ele ments are allocated and the last one is set to NULL Note that in this case type must be a pointer type ie a type that canonicalizes to pointer otherwise an error is signaled Examples CFFI gt foreign alloc char gt lt A Mac Pointer x102D80 gt A pointer to 1 byte of memory CFFI gt foreign alloc char count 20 gt lt A Mac Pointer x1024A0 gt A pointer to 20 bytes of memory CFFI gt foreign alloc int initial element 12 gt lt A Mac Pointer x1028B0 gt Chapter 7 Pointers 61 CFFI gt mem ref int 12 CFFI gt foreign alloc int initial contents 1 2 3 lt A Mac Pointer x102950 gt CFFI gt loo
62. hat must know about the values contained in a relevant struct If the library you are interfacing returns an opaque pointer that needs only be passed to other C library functions by all means just use pointer or a type safe definition munged together with defctype and type translation To pass or return a structure by value to a function load the cff libffi system and specify the structure as struct structure name To pass or return the pointer you can use either pointer or pointer struct structure name Compatibility note Previous versions of CFFI accepted the bare structure name as a type specification which was interpreted as a pointer to the structure This is deprecated and produces a style warning Using this deprecated form means that mem aref page 67 retains its prior meaning and returns a pointer Using the struct structure name form for the type mem aref page 67 provides a Lisp object translated from the structure by default a plist Thus the semantics are consistent with all types in returning the object as represented in Lisp and not a pointer with the exception of the bare structure compatibility retained In order to obtain the pointer you should use the function mem aptr page 66 See defcstruct page 33 for more details 6 7 Allocating Foreign Objects See Section 7 2 Allocating Foreign Memory page 57 Chapter 6 Foreign Types 29 convert from foreign Syntax convert from fore
63. he converted C string will have dynamic extent i e it will be automatically freed after the foreign function returns In addition to Lisp strings this type will accept foreign pointers and pass them unmod ified A method for free translated object page 51 is specialized for this type So for exam ple foreign strings allocated by this type and passed to a foreign function will be freed after the function returns CFFI gt foreign funcall getenv string SHELL string gt bin bash CFFI gt with foreign string str abcdef foreign funcall strlen string str int gt 6 stringt tptr Foreign Type Like string but returns a list with two values when convert from C to Lisp a Lisp string and the C string s foreign pointer CFFI gt foreign funcall getenv string SHELL string ptr gt bin bash SB SYS INT SAP XBFFFFC6F Chapter 6 Foreign Types 24 boolean amp optional base type int Foreign Type The boolean type converts between a Lisp boolean and a C boolean It canonicalizes to base type which is int by default convert to foreign nil boolean gt 0 convert to foreign t boolean gt 1 convert from foreign 0 boolean gt nil convert from foreign 1 boolean gt t bool Foreign Type The bool type represents the C99 _Bool or C bool Its size is usually 1 byte except on OSX where it s an int wrapper base type amp key to c from c Foreign Type The wrapper
64. ides a declarative interface for defining Lisp functions that call foreign functions When one of lisp name or foreign name is omitted the other is automatically derived using the following rules e Foreign names are converted to Lisp names by uppercasing and replacing underscores with hyphens e Lisp names are converted to foreign names by lowercasing and replacing hyphens with underscores If you place the symbol amp rest in the end of the argument list after the fixed arguments defcfun will treat the foreign function as a variadic function The variadic arguments should be passed in a way similar to what foreign funcall would expect Unlike foreign funcall though defcfun will take care of doing argument promotion Note that in this case defcfun will generate a Lisp macro instead of a function and will only work for Lisps that support foreign funcall If a foreign structure is to be passed or returned by value that is the type is of the form struct then the cffi libffi system must be loaded which in turn depends on libfh including the header files Failure to load that system will result in an error Variadic functions cannot at present accept or return structures by value Chapter 10 Functions Examples defcfun strlen int Calculate the length of a string n string CFFI gt strlen 123 gt 3 defcfun abs c abs int n int CFFI gt c abs 42 gt 42 Function without arguments
65. ign Interfaces and CFFI 17 with the data directly As part of calling curl_easy_perform later we ll bind that variable to a closure with more useful lexical bindings than the top level defcallback form Finally we make a halfhearted effort to prevent non local exits from unwinding the C stack covering the most likely case with an error handler which is usually triggered unexpectedly The reason is that most C code is written to understand its own idiosyncratic error condition implemented above in the case of curl easy perform and more undefined behavior can result if we just wipe C stack frames without allowing them to execute whatever cleanup actions as they like Using the CURLoption enumeration in curl h once more we can describe the new option by modifying and reevaluating define curl options define curl options curl option long 0 objectpoint 10000 functionpoint 20000 off t 30000 noprogress long 43 nosignal long 99 errorbuffer objectpoint 10 url objectpoint 2 writefunction functionpoint 11 new item here N N INN Finally we can use the defined callback and the new set curl option writefunction to finish configuring the easy handle using the callback macro to retrieve a CFFI pointer which works like a function pointer in code CFFI USER gt set curl option writefunction easy handle callback easy write 0 4 10 A complete FFI With all options finally set and a medium level in
66. ign foreign value type value Function Arguments and Values foreign value The primitive C value as returned from a primitive foreign function or from convert to foreign type A CFFI type specifier value The Lisp value translated from foreign value Description This is an external interface to the type translation facility In the implementation all for eign functions are ultimately defined as type translation wrappers around primitive foreign function invocations This function is available mostly for inspection of the type translation process and possibly optimization of special cases of your foreign function calls Its behavior is better described under translate from foreign s documentation Examples CFFI USER gt convert to foreign a boat string lt FOREIGN ADDRESS x097ACDCO gt T CFFI USER gt convert from foreign string a boat See Also convert to foreign page 30 free converted object page 50 translate from foreign page 52 Chapter 6 Foreign Types 30 convert to foreign Syntax convert to foreign value type foreign value Function alloc params Arguments and Values value The Lisp object to be translated to a foreign object type A CFFI type specifier foreign value The primitive C value ready to be passed to a primitive foreign function alloc params Something of a translation state you must pass it to free converted object along with the foreign value for th
67. ing the abstraction page 9 The first reason also applies to CURLOPT_URL which we will use to illustrate the point Assuming we have changed the type of the third argument underlying set curl option url to string look at these two equivalent forms set curl option url easy handle http www cliki net CFFI with foreign string url http www cliki net CFFI foreign funcall curl easy setopt easy handle easy handle curl option url pointer url curl code The latter in fact is mostly equivalent to what a foreign function call s macroexpansion actually does As you can see the Lisp string http www cliki net CFFI is copied into a char array and null terminated the pointer to beginning of this array now a C string is passed as a CFFI pointer to the foreign function Unfortunately the C abstraction has failed us and we must break it While string works well for many char arguments it does not for cases like this As the curl easy setopt documentation explains The string must remain present until curl no longer needs it as it doesn t copy the string The C string created by with foreign string however only has dynamic extent it is deallocated when the body above containing the foreign funcall form exits Chapter 4 An Introduction to Foreign Interfaces and CFFI 13 If we are supposed to keep the C string around but it goes away what happens when some libcurl function tries to access the URL st
68. ion on the warts on particular Lisp implementations see Chapter 3 Implementation Support page 3 e The tutorial includes a treatment of the primary intractable limitation of CFFI or any FFI that the abstractions commonly used by C are insufficiently expressive See Section 4 6 Breaking the abstraction page 9 for more details e C structs cannot be passed by value Appendix A Platform specific features 119 Appendix A Platform specific features Whenever a backend doesn t support one of CFFI s features a specific symbol is pushed onto common lisp features The meanings of these symbols follow cffi sys flat namespace This Lisp has a flat namespace for foreign symbols meaning that you won t be able to load two different libraries with homograph functions and successfully differentiate them through the library option to defcfun defcvar etc cffi sys no foreign funcall The macro foreign funcall is not available On such platforms the only way to call a foreign function is through defcfun See foreign funcall page 91 and defcfun page 89 cffi sys no long long The C long long type is not available as a foreign type However on such platforms CFFI provides its own implementation of the long long type for all of operations in chapters Chapter 6 Foreign Types page 22 Chapter 7 Pointers page 57 and Chapter 9 Variables page 84 The function ality described in Chapter 10 Functions page 88 and Chapter 1
69. is also albeit informally 7 1 Basic Pointer Operations Manipulating pointers proper can be accomplished through most of the other operations defined in the Pointers dictionary such as make pointer pointer address and pointer eq When using them keep in mind that they merely manipulate the Lisp representation of pointers not the values they point to foreign pointer Lisp Type The pointers representations differ from implementation to implementation and have different types foreign pointer provides a portable type alias to each of these types 7 2 Allocating Foreign Memory CFFI provides support for stack and heap C memory allocation Stack allocation done with with foreign object is sometimes called dynamic allocation in Lisp because memory allocated as such has dynamic extent much as with let bindings of special variables This should not be confused with what C calls dynamic allocation or that done with malloc and friends This sort of heap allocation is done with foreign alloc creating objects that exist until freed with foreign free 7 3 Accessing Foreign Memory When manipulating raw C data consider that all pointers are pointing to an array When you only want one C value such as a single struct this array only has one such value It is worthwhile to remember that everything is an array though because this is also the semantic that C imposes natively C values are accessed as the setf able places d
70. is called for often using C functions provided by the implementation It also translates between the calling conventions of the language and C Common Lisp Bindings are written in Lisp They can be created at will by Lisp programs Lisp programmers can write new bindings and add them to the image using a listener such as SLIME as easily as with regular Lisp definitions The only foreign library to load is the one being wrapped the one with the pure C interface no C or other non Lisp compilation is required We believe the advantages of the Common Lisp approach far outweigh any disadvantages Incremental development with a listener can be as productive for C binding development as it is with other Lisp development Keeping it in the Lisp family as it were makes it much easier for you and other Lisp programmers to load and use the bindings Common Lisp implementations such as CMUCL freed from having to provide a C interface to their own objects are thus freed to be implemented in another language as CMUCL is while still allowing programmers to call foreign functions Perhaps the greatest advantage is that using an FFI doesn t obligate you to become a professional binding developer Writers of bindings for other languages usually end up maintaining or failing to maintain complete bindings to the foreign library Using an FFI however means if you only need one or two functions you can write bindings for only those functions and
71. izes to a built in type such as long or pointer Used for simple CFFI types Aggregate Contain an embedded structure or union or an array of objects Used for aggregate CFFI types The use of CLOS terminology for the structure related features is intentional structure definitions are very much like classes with far fewer features Examples defcstruct point Point structure x int y int CFFI gt with foreign object ptr point Chapter 6 Foreign Types 34 Initialize the slots setf foreign slot value ptr point x 42 foreign slot value ptr point y 42 Return a list with the coordinates with foreign slots x y ptr point list x y gt 42 42 Using the size and offset options to define a partial structure this is useful when you are interested in only a few slots of a big foreign structure defcstruct foo size 32 Some struct with 32 bytes lt 16 bytes we don t care about x int offset 16 an int at offset 16 y int another int at offset 16 sizeof int lt a couple more bytes we don t care about z char offset 24 a char at offset 24 lt 7 more bytes ignored since size is 32 CFFI gt foreign type size foo gt 32 Using count to define arrays inside of a struct defcstruct video tuner name char count 32 See Also foreign slot pointer page 46 foreign slot value page 47 with foreign slots page 55
72. l time pointer null pointer int foreign funcall gmtime pointer time pointer struct tm lt A Mac Pointer x102A30 gt CFFI gt with foreign slots sec min hour mday mon year struct tm format nil A A A A A A hour min sec 1900 year mon mday gt 7 22 47 2005 8 2 Chapter 6 Foreign Types See Also defestruct page 33 defcunion page 35 foreign slot value page 47 56 Chapter 7 Pointers 57 7 Pointers All C data in CFFI is referenced through pointers This includes defined C variables that hold immediate values and integers To see why this is consider the case of the C integer It is not only an arbitrary representation for an integer congruent to Lisp s fixnums the C integer has a specific bit pattern in memory defined by the C ABI Lisp has no such constraint on its fixnums therefore it only makes sense to think of fixnums as C integers if you assume that CFFI converts them when necessary such as when storing one for use in a C function call or as the value of a C variable This requires defining an area of memory represented through an effective address and storing it there Due to this compartmentalization it only makes sense to manipulate raw C data in Lisp through pointers to it For example while there may be a Lisp representation of a struct that is converted to C at store time you may only manipulate its raw data through a pointer The C compiler does th
73. lementation specific Notes e Corman Lisp does not support foreign funcall On implementations that don t support foreign funcall cffi sys no foreign funcall will be present in features Note in these Lisps you can still use the defcfun interface Examples CFFI gt foreign funcall strlen string foo int gt 3 Given the C code void print_number int n printf N d n n Chapter 10 Functions 92 CFFI gt foreign funcall print_number int 123456 4 N 123456 NIL Or equivalently CFFI gt foreign funcall print_number int 123456 void N 123456 gt NIL CFFI gt foreign funcall printf string format nil As d string So long and thanks for all the fish int 42 int So long and thanks for all the fish 42 gt 41 See Also defcfun page 89 foreign funcall pointer page 93 Chapter 10 Functions 93 foreign funcall pointer Syntax foreign funcall pointer pointer options amp rest arguments Macro return value arguments arg type arg return type options amp key convention Arguments and Values pointer A foreign pointer arg type A foreign type arg An argument of type arg type return type A foreign type void by default return value A lisp object convention One of cdecl default or stdcall Description The foreign funcall macro is the main primitive for calling foreign functions Note The return value of foreign funcall
74. looking for a FILE CURLOPT_ERRORBUFFER is looking for a char so there is no obvious CFFI type but pointer The first thing to note is that nowhere in the C interface includes this information it can only be found in the manual We could disjoin these clearly different types ourselves by splitting objectpoint into filepoint and charpoint but we are still breaking the abstraction because we have to augment the entire enumeration form with this additional information The second is that the CURLOPT_WRITEDATA argument is completely incompatible with the desired Lisp data a stream It is probably acceptable if we are controlling every file we might want to use as this argument in which case we can just call the foreign function fopen Regardless though we can t write to arbitrary streams which is exactly what we want to do for this application Finally note that the curl_easy_setopt interface itself is a hack intended to work around some of the drawbacks of C The definition of Curl_setopt while long is far less 5 Another possibility is to allow the caller to specify the desired C type of the third argument This is essentially what happens in a call to the function written in C 6 See Section Other Kinds of Streams in GNU C Library Reference for a GNU only way to extend the FILE type You could use this to convert Lisp streams to the needed C data This would be quite involved and far outside the scope of this tutorial
75. mLesec tanon EEEE E EEE 89 defcstruct name and options amp body doc and slots name 33 defctype name base type amp optional documentation eene 36 defcunion name amp body doc and slots name PM 35 defcvar name and options type amp optional documentation lisp name 85 define ei disp hae andi pieces sete se Sake 115 define foreign library name and options load clause gt name 101 define foreign type class name supers slots amp rest options class name 38 define parse method name lambda list amp body body name i ee Ser by b Ie een ated 39 defining callbacks s ee wenn 16 defining type translation compiler macros 26 dynamic extent 2elxr n Henne 12 E enumeration rs sese seeds mare RR ne T F FILE and streams 0 ccc cece cece cece ee 9 Index foreign arguments 0 eee rj foreign functions and data 000 4 foreign library load 0 02000e 6 foreign values with dynamic extent 12 foreign alloc type amp key initial element initial contents count 1 null terminated p pointer 60 foreign bitfield symbols type value Symbol Ss clits hehe e ARRA E LIRE GS 40 foreign bitfield value type symbols value EE 41 foreign enum keyword type value amp key errorp keyword ervser used rpieibpeWet 42 foreign enum v
76. me and options structure name structure name amp key size doc and slots docstring slot name slot type amp key count offset Arguments and Values structure name The name of new structure type docstring A documentation string ignored slot name A symbol naming the slot It must be unique among slot names in this structure size Use this option to override the size in bytes of the struct slot type The type specifier for the slot count Used to declare an array of size count inside the structure Defaults to 1 as such an array and a single element are semantically equivalent offset Overrides the slot s offset The next slot s offset is calculated based on this one Description This defines a new CFFI aggregate type akin to C structs In other words it specifies that foreign objects of the type structure name are groups of different pieces of data or slots of the slot types distinguished from each other by the slot names Each structure is located in memory at a position and the slots are allocated sequentially beginning at that point in memory with some padding allowances as defined by the C ABI unless otherwise requested by specifying an offset from the beginning of the structure offset 0 In other words it is isomorphic to the C struct giving several extra features There are two kinds of slots for the two kinds of CFFI types Simple Contain a single instance of a type that canonical
77. ments and Values string A Lisp string buffer A foreign pointer bufsize An integer start end Bounding index designators of string 0 and nil by default offset An integer greater than or equal to 0 Defauls to 0 encoding Foreign encoding Defaults to default foreign encoding Description The lisp string to foreign function copies at most bufsize 1 octets from a Lisp string using the specified encoding into buffer offset The foreign string will be null terminated Start specifies an offset into string and end marks the position following the last element of the foreign string Examples CFFI gt with foreign pointer as string str 255 lisp string to foreign Hello foreign world str 6 Hello See Also foreign string alloc page 78 foreign string to lisp page 80 with foreign pointer as string page 83 Chapter 8 Strings 82 with foreign string with foreign strings Syntax with foreign string var or vars string amp rest args amp body Macro body with foreign strings bindings amp body body Macro var or vars var var amp optional octet size var bindings var or vars string amp rest args Arguments and Values var byte size var A symbol string A Lisp string body A list of forms to be executed Description The with foreign string macro will bind var to a newly allocated foreign string contain ing string Args is passed to the underlying foreign string alloc call
78. meworks on Darwin and derivatives like Mac OS X and d1l files on Windows Bringing one of these libraries into the Lisp image is normally a two step process 1 Describe to CFFI how to load the library at some future point depending on platform and other factors with a define foreign library top level form 2 Load the library so defined with either a top level use foreign library form or by calling the function load foreign library See Section 4 3 Loading foreign libraries page 5 for a working example of the above two steps 11 2 Library definition style Looking at the libcurl library definition presented earlier you may ask why we did not simply do this define foreign library libcurl t default libcurl Indeed this would work just as well on the computer on which I tested the tutorial There are a couple of good reasons to provide the so s current version number however Namely the versionless so is not packaged on most UNIX systems along with the actual fully versioned library instead it is included in the development package along with C headers and static a libraries The reason CFFI does not try to account for this lies in the meaning of the version num bers A full treatment of shared library versions is beyond this manual s scope see Section Library interface versions in GNU Libtool for helpful information for the unfamiliar For our purposes consider that a mi
79. nd managing CFFI and its dependencies Chapter 3 Implementation Support 3 3 Implementation Support CFFI supports various free and commercial Lisp implementations Allegro CL Corman CL CLISP CMUCL ECL LispWorks Clozure CL SBCL and the Scieneer CL In general you should work with the latest versions of each implementation since those will usually be tested against recent versions of CFFI more often and might include necessary features or bug fixes Reasonable patches for compatibility with earlier versions are welcome nevertheless 3 1 Limitations Some features are not supported in all implementations Allegro CL e Does not support the long long type natively e Unicode support is limited to the Basic Multilingual Plane 16 bit code points CMUCL e No Unicode support 8 bit code points Corman CL e Does not support foreign funcall ECL e On platforms where ECL s dynamic FFI is not supported ie when dffi is not present in features cffi load foreign library does not work and you must use ECL s own ffi load foreign library with a constant string argument e Does not support the long long type natively e Unicode support is not enabled by default Lispworks e Does not completely support the long long type natively in 32 bit platforms e Unicode support is limited to the Basic Multilingual Plane 16 bit code points SBCL e Not all platforms support callbacks Chapter 4 An Introduction to Foreign In
80. ne foreign library clause t default libcurl should be satisfactory and will adapt to various operating systems 4 4 Initializing libcurl After the introductory matter the tutorial goes on to present the first function you should use CURLcode curl global init long flags Let s pick this apart into appropriate Lisp code A CURLcode is the universal error code curl curl h says no return code will ever be removed and new ones will be added to the end defctype curl code int 333 Initialize libcurl with FLAGS defcfun curl_global_init curl code flags long Implementor s note By default CF FI assumes the UNIX viewpoint that there is one C symbol namespace containing all symbols in all loaded objects This is not so on Windows and Darwin but we emulate UNIX s behaviour there defcfun page 89 for more details Note the parallels with the original C declaration We ve defined curl code as a wrap ping type for int right now it only marks it as special but later we will do something more interesting with it The point is that we don t have to do it yet Looking at curl h CURL GLOBAL NOTHING a possible value for flags above is defined as 0 So we can now call the function Chapter 4 An Introduction to Foreign Interfaces and CFFI 7 CFFI USER gt curl global init 0 gt 0 Looking at curl h again 0 means CURLE_OK so it looks like the call succeeded Note that CFFI conver
81. ned long long long and unsigned long long respectively int8 uint8 int16 uint16 int32 uint32 Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Foreign Type Chapter 6 Foreign Types 23 int64 Foreign Type uint64 Foreign Type Foreign integer types of specific sizes corresponding to the C types defined in stdint h float Foreign Type double Foreign Type On all systems the float and double types represent a C float and double respec tively On most but not all systems float and double represent a Lisp single float and double float respectively It is not so useful to consider the relationship between Lisp types and C types as isomorphic as simply to recognize the relationship and relative precision among each respective category long double Foreign Type This type is only supported on SCL pointer amp optional type Foreign Type A foreign pointer to an object of any type corresponding to void You can optionally specify type of pointer e g pointer char Although CFFI won t do anything with that information yet it is useful for documentation purposes void Foreign Type No type at all Only valid as the return type of a function 6 2 Other Types CFFI also provides a few useful types that aren t built in C types string Foreign Type The string type performs automatic conversion between Lisp and C strings Note that in the case of functions t
82. ns nil value An integer Description The function foreign enum value returns the value that corresponds to keyword in type An error is signaled if type doesn t contain such keyword and errorp is true Examples defcenum boolean no yes CFFI gt foreign enum value boolean yes gt 1 See Also defcenum page 37 foreign enum key word page 42 Chapter 6 Foreign Types 44 foreign slot names Syntax foreign slot names type names Function Arguments and Values type A foreign struct type names A list Description The function foreign slot names returns a potentially shared list of slot names for the given structure type This list has no particular order Examples defcstruct timeval tv secs long tv usecs long CFFI gt foreign slot names struct timeval gt TV SECS TV USECS See Also defestruct page 33 foreign slot offset page 45 foreign slot value page 47 foreign slot pointer page 46 Chapter 6 Foreign Types foreign slot offset Syntax foreign slot offset type slot name offset Arguments and Values type A foreign struct type slot name A symbol offset An integer Description 45 Function The function foreign slot offset returns the offset in bytes of a slot in a foreign struct type Examples defcstruct timeval tv secs long tv usecs long CFFI gt foreign slot offset struct timeval tv secs
83. nt in favor of FFI in general CFFT s primary role in any image is to mediate between Lisp developers and the widely varying FFIs present in the various Lisp implementations it supports With CFFI you can define foreign function interfaces while still maintaining portability between implementa tions It is not the first Common Lisp package with this objective however it is meant to be a more malleable framework than similar packages Design Philosophy e Pointers do not carry around type information Instead type information is supplied when pointers are dereferenced e A type safe pointer interface can be developed on top of an untyped one It is difficult to do the opposite e Functions are better than macros When a macro could be used for performance use a compiler macro instead Chapter 2 Installation 2 2 Installation CFFI can be obtained through one of the following means available through its website e official release tarballs e git repository In addition you will need to obtain and install the following dependencies e Babel a charset encoding decoding library e Alexandria a collection of portable public domain utilities e trivial features a portability layer that ensures consistent features across multiple Common Lisp implementations Furthermore if you wish to run the testsuite RT is required You may find mechanisms such as clbuild recommended or ASDF Install not as rec ommendable helpful in getting a
84. obe file if found the absolute path is passed to the implementation s loader 3 Ifa list the meaning depends on first library framework The second list element is taken to be a Darwin framework name which is then searched in darwin framework directories and loaded when found vor Each remaining list element itself a library designator is loaded in order until one succeeds default The name is transformed according to the platform s naming convention to shared libraries and the resultant string is loaded as a library designator For example on UNIX the name is suffixed with so If the load fails signal a load foreign library error Please note For system libraries you should not need to specify the directory containing the library Each operating system has its own idea of a default search path and you should rely on it when it is reasonable Implementation specific Notes On ECL platforms where its dynamic FFI is not supported ie when dffi is not present in features cffi load foreign library does not work and you must use ECL s own ffi load foreign library with a constant string argument Examples See Section 4 3 Loading foreign libraries page 5 Chapter 11 Libraries See Also close foreign library page 99 darwin framework directories page 100 define foreign library page 101 foreign library directories page 103 load foreign library error page 107 use foreign librar
85. olean type if value 1 0 defmethod expand from foreign value type my boolean type not zerop value And here s what the macroexpansion of a function using this type would look like CFFI gt macroexpand 1 defcfun bar my boolean x my boolean simplified downcased etc defun bar x let g3182 if x 1 0 not zerop foreign funcall bar int g3182 int No generic function overhead Let s go back to our my string type The expansion interface has no equivalent of free translated object you must instead define a method on expand to foreign dyn the Chapter 6 Foreign Types 27 third generic function in this interface This is especially useful when you can allocate something much more efficiently if you know the object has dynamic extent as is the case with function calls that don t save the relevant allocated arguments This exactly what we need for the my string type defmethod expand from foreign form type my string type foreign string to lisp form defmethod expand to foreign dyn value var body type my string type let encoding string type encoding type with foreign string var value encoding encoding body So let s look at the macro expansion CFFI gt macroexpand 1 defcfun foo my string x my string simplified downcased etc defun foo x with foreign string G2021 X encoding utf 8 foreign strin
86. options accept a function pointer In particular we need one function pointer to set as CURLOPT_ Chapter 4 An Introduction to Foreign Interfaces and CFFI 16 WRITEFUNCTION to be called by libcurl rather than the reverse in order to receive data as it is downloaded A binding writer without the aid of FFI usually approaches this problem by writing a C function that accepts C data converts to the language s internal objects and calls the callback provided by the user again in a reverse of usual practices The CFFI approach to callbacks precisely mirrors its differences with the non FFI ap proach on the calling C from Lisp side which we have dealt with exclusively up to now That is you define a callback function in Lisp using defcallback and CFFI effectively creates a C function to be passed as a function pointer Implementor s note This is much trickier than calling C functions from Lisp as it literally involves somehow generating a new C function that is as good as any created by the compiler Therefore not all Lisps support them See Chapter 3 Implementation Support page 3 for information about CFFI support issues in this and other areas You may want to consider changing to a Lisp that supports callbacks in order to continue with this tutorial Defining a callback is very similar to defining a callout the main difference is that we must provide some Lisp forms to be evaluated as part of the callback Here is the signatu
87. ows NAME TYPE NUMBER Where the arguments are as they are with the CINIT macro defined in curl h except NAME is a keyword TYPE OFFSETS is a plist of TYPEs to their integer offsets as defined by the CURLOPTTYPE_LONG et al constants in curl h Also define functions for each option named set TYPE NAME OPTION NAME where OPTION NAME is the NAME from the above destructuring flet enumerated value type offset getf type offsets type offset map PROCEDURE destructuring each of ENUM ARGS map enum args procedure mapcar lambda arg apply procedure arg enum args build a name like SET CURL OPTION NOSIGNAL make setter name option name intern concatenate string SET symbol name type name symbol name option name progn defcenum type name map enum args lambda name type number list name enumerated value type number map enum args lambda name type number declare ignore number define curl option setter make setter name name type name name ecase type long long objectpoint pointer functionpoint pointer off t long gt type name Macroexpanding our define curl options form once more we see something different progn defcenum curl option noprogress 43 nosignal 99 errorbuffer 10010 url 10002 define curl option setter set curl option noprogress curl option noprogress long define curl option setter set
88. oyed is mostly compliant with ANSI C SWIG A foreign interface generator originally designed to generate Python bindings it has been ported to many other systems including CFFI in version 1 3 28 Includes its own C declaration munger not intended to be fully compliant with ANSI C First this manual does not describe use of these other programs they have documen tation of their own If you have problems using a generated interface please look at the output CFFI forms and verify that they are a correct CFFI interface to the library in ques tion if they are correct contact CFFI developers with details keeping in mind that they communicate in terms of those forms rather than any particular wrapper generator Oth erwise contact the maintainers of the wrapper generator you are using provided you can reasonably expect more accuracy from the generator When is more accuracy an unreasonable expectation As described in the tutorial see Section 4 6 Breaking the abstraction page 9 the information in C declarations is in sufficient to completely describe every interface In fact it is quite common to run into an interface that cannot be handled automatically and generators should be excused from generating a complete interface in these cases As further described in the tutorial the thinnest Lisp interface to a C function is not always the most pleasant one In many cases you will want to manually write a Lispier interface to the C fun
89. p for i from 0 below 3 collect mem aref int i gt 123 CFFI gt foreign alloc int initial contents 1 2 3 lt A Mac Pointer x102960 gt CFFI gt loop for i from 0 below 3 collect mem aref int i gt 1 2 3 Allocate a char pointer that points to newly allocated memory 333 by the string type translator for the string foo CFFI gt foreign alloc string initial element foo gt lt A Mac Pointer x102C40 gt Allocate a null terminated array of strings 333 Note FOREIGN STRING TO LISP returns NIL when passed a null pointer CFFI gt foreign alloc string initial contents foo bar baz null terminated p t lt A Mac Pointer x102D20 gt CFFI gt loop for i from 0 below 4 collect mem aref string i gt foo bar baz NIL CFFI gt progn dotimes i 3 foreign free mem aref pointer i foreign free gt nil See Also foreign free page 59 with foreign object page 74 with foreign pointer page 75 Chapter 7 Pointers 62 foreign symbol pointer Syntax foreign symbol pointer foreign name amp key library Function pointer Arguments and Values foreign name A string pointer A foreign pointer or nil library A Lisp symbol or an instance of foreign library Description The function foreign symbol pointer will return a foreign pointer corresponding to the foreign symbol denoted by the string foreign name If a foreign symbol name
90. page 69 null pointer p page 70 Chapter 7 Pointers 64 incf pointer Syntax incf pointer place amp optional offset 1 new pointer Macro Arguments and Values place A setf place new pointer A foreign pointer offset An integer Description The incf pointer macro takes the foreign pointer from place and creates a new pointer incremented by offset bytes and which is stored in place Examples CFFI gt defparameter two words foreign string alloc Common Lisp gt TWO WORDS CFFI gt defparameter one word two words DNE WORD CFFI gt incf pointer one word 7 gt SB SYS INT SAP X00600457 CFFI gt foreign string to lisp one word gt Lisp CFFI gt foreign string to lisp two words gt Common Lisp See Also inc pointer page 63 make pointer page 65 pointerp page 71 null pointer page 69 null pointer p page 70 Chapter 7 Pointers make pointer Syntax make pointer address ptr Arguments and Values address An integer ptr A foreign pointer Description The function make pointer will return a foreign pointer pointing to address Examples CFFI gt make pointer 42 lt FOREIGN ADDRESS x0000002A gt CFFI gt pointerp gt T CFFI gt pointer address gt 42 CFFI gt inc pointer 42 lt FOREIGN ADDRESS x00000000 gt CFFI gt null pointer p T CFFI gt typep foreign pointer T See Also
91. pe class option tells CFFI that this type will ultimately be passed to and received from foreign code as a pointer Now you need to tell CFFI how to parse a type specification such as my string encoding utf8 into an instance of my string type We do that with define parse method define parse method my string amp key encoding utf 8 make instance my string type encoding encoding The next section describes how make this type actually translate between C and Lisp strings 6 4 Foreign Type Translators Type translators are used to automatically convert Lisp values to or from foreign values For example using type translators one can take the my string type defined in the previous section and specify that it should e convert C strings to Lisp strings e convert Lisp strings to newly allocated C strings e free said C strings when they are no longer needed In order to tell CFFI how to automatically convert Lisp values to foreign values define a specialized method for the translate to foreign generic function Define a method that converts Lisp strings to C strings defmethod translate to foreign string type my string type foreign string alloc string encoding string type encoding type From now on whenever an object is passed as a my string to a foreign function this method will be invoked to convert the Lisp value To perform the inverse operation which is needed for functions that return a my string
92. ption The function null pointer returns a null pointer Examples CFFI gt null pointer gt lt A Null Mac Pointer CFFI gt pointerp gt T See Also null pointer p page 70 make pointer page 65 69 Function Chapter 7 Pointers 70 null pointer p Syntax null pointer p ptr boolean Function Arguments and Values ptr A foreign pointer that may be a null pointer boolean T or NIL Description The function null pointer p returns true if ptr is a null pointer and false otherwise Examples CFFI gt null pointer p null pointer T defun contains str p big little not null pointer p foreign funcall strstr string big string little pointer CFFI gt contains str p Popcorns corn T CFFI gt contains str p Popcorns salt NIL See Also null pointer page 69 pointerp page 71 Chapter 7 Pointers 71 pointerp Syntax pointerp ptr boolean Function Arguments and Values ptr An object that may be a foreign pointer boolean T or NIL Description The function pointerp returns true if ptr is a foreign pointer and false otherwise Implementation specific Notes In Allegro CL foreign pointers are integers thus in this implementation pointerp will return true for any ordinary integer Examples CFFI gt foreign alloc 32 lt A Mac Pointer x102D20 gt CFFI gt pointerp gt T CFFI gt pointerp this is not a pointer
93. pts can be either a symbol as name or a list name amp key base type define constants If define constants is non null a Lisp constant will be defined for each enum member constantenum name and opts amp rest elements Grovel Form Defines an enumeration of pre processor constants with elements specified as lisp name amp rest c names amp key optional documentation name and opts can be ei ther a symbol as name or a list name amp key base type define constants If define constants is non null a Lisp constant will be defined for each enum member Chapter 13 The Groveller 116 This example defines af inet to represent the value held by AF_INET or PF_INET whichever the pre processor finds first Similarly for af packet but no error will be signalled if the platform supports neither AF_PACKET nor PF_PACKET constantenum address family af inet AF INET PF INET documentation IPv4 Protocol family C af local AF UNIX AF LOCAL PF UNIX PF LOCAL documentation File domain sockets af inet6 AF INET6 PF INET6 documentation IPv6 Protocol family af packet AF PACKET PF PACKET documentation Raw packet access optional t bitfield name and opts amp rest elements Grovel Form Defines a bitfield with elements specified as lisp name amp rest c names amp key optional documentation name and opts can be either a symbol as name or a list name amp key base type For example
94. re for the function the writefunction option takes size t function void ptr size t size size t nmemb void stream Implementor s note size_t is almost always an unsigned int You can get this and many other types using feature tests for your system by using cffi grovel The above signature trivially translates into a CFFI defcallback form as follows Alias in case size_t changes defctype size unsigned int To be set as the CURLOPT WRITEFUNCTION of every easy handle defcallback easy write size ptr pointer size size nmemb size stream pointer let data size size nmemb handler case We use the dynamically bound easy write procedure to call a closure with useful lexical context progn funcall symbol value easy write procedure foreign string to lisp ptr count data size data size indicates success The WRITEFUNCTION should return something other than the bytes available to signal an error error if zerop data size 1 0 First note the correlation of the first few forms used to declare the C function s signa ture with the signature in C syntax We provide a Lisp name for the function its return type and a name and type for each argument In the body we call the dynamically bound easy write procedure with a finished translation of pulling together the raw data and size into a Lisp string rather than deal Chapter 4 An Introduction to Fore
95. ring We have reentered the dreaded world of C undefined behavior In some Lisps it will probably get a chunk of the Lisp C stack You may segfault You may get some random piece of other data from the heap Maybe in a world where dynamic extent is defined to be infinite extent everything will turn out fine Regardless results are likely to be almost universally unpleasant Returning to the current set curl option url interface here is what we must do let easy handle unwind protect with foreign string url http www cliki net CFFI setf easy handle curl easy init set curl option url easy handle url do more with the easy handle like actually get the URLI when easy handle curl easy cleanup easy handle That is fine for the single string defined here but for every string option we want to pass we have to surround the body of with foreign string with another with foreign string wrapper or else do some extremely error prone pointer manipulation and size calculation in advance We could alleviate some of the pain with a recursively expanding macro but this would not remove the need to modify the block every time we want to add an option anathema as it is to a modular interface Before modifying the code to account for this case consider the other reason we can t simply use string as the foreign type In C a char is a char not necessarily a string The option CURLOPT_ERRORBUFFER accepts a
96. s defcfun qsort void base pointer nmemb int size int fun compar pointer defcallback lt int a pointer b pointer let x mem ref a int y mem ref b int cond gt x y 1 lt xy 1 t 0 CFFI gt with foreign object array int 10 Initialize array loop for i from 0 and n in 7 210435169 8 do setf mem aref array int i n Chapter 12 Callbacks 112 Sort it qsort array 10 foreign type size int callback Return it as a list loop for i from 0 below 10 collect mem aref array int i gt 123456789 10 See Also callback page 110 get callback page 113 Chapter 12 Callbacks 113 get callback Syntax get callback symbol pointer Accessor Arguments and Values symbol A symbol denoting a callback pointer A pointer Description This is the functional version of the callback macro It returns a pointer to the callback named by symbol suitable for example to pass as arguments to foreign functions Examples CFFI gt defcallback sum int a int b int a b gt SUM CFFI gt get callback sum gt lt A Mac Pointer x102350 gt See Also callback page 110 defcallback page 111 Chapter 13 The Groveller 114 13 The Groveller CFFI Grovel is a tool which makes it easier to write CFFI declarations for libraries that are implemented in C That is it grovels through the system headers getting
97. s Chapter 12 Callbacks 110 callback Syntax callback symbol gt pointer Macro Arguments and Values symbol A symbol denoting a callback pointer new value A pointer Description The callback macro is analogous to the standard CL special operator function and will return a pointer to the callback denoted by the symbol name Examples CFFI gt defcallback sum int a int b int a b gt SUM CFFI gt callback sum gt lt A Mac Pointer x102350 gt See Also get callback page 113 defcallback page 111 Chapter 12 Callbacks 111 defcallback Syntax defcallback name and options return type arguments amp body Macro body name name and options name name amp key convention arguments arg name arg type Arguments and Values name A symbol naming the callback created return type The foreign type for the callback s return value arg name A symbol arg type A foreign type convention One of cdecl default or stdcall Description The defcallback macro defines a Lisp function that can be called from C The arguments passed to this function will be converted to the appropriate Lisp representation and its return value will be converted to its C representation This Lisp function can be accessed by the callback macro or the get callback function Portability note defcallback will not work correctly on some Lisps if it s not a top level form Example
98. s always preferred In fact many prefer to stay in Lisp and break the encapsulation anyway placing the burden of correct library interface definition on the library 2 w Specifically UFFI an older FFI that takes a somewhat different approach compared to CFFI I believe that these days December 2005 CFFI is more portable and actively developed though not as mature yet Consensus in the free UNIX Common Lisp community seems to be that CFFI is preferred for new development though UFFI will likely go on for quite some time as many projects already use it CFFI includes the UFFI COMPAT package for complete compatibility with UFFI Chapter 4 An Introduction to Foreign Interfaces and CFFI 6 asdf oos asdf load op cffi Nothing special about the CFFI USER package We re just using it as a substitute for your own CL package defpackage cffi user use common lisp cffi in package cffi user define foreign library libcurl darwin or libcurl 3 dylib libcurl dylib unix or libcurl so 3 libcurl so t default libcurl use foreign library libcurl Using define foreign library and use foreign library we have loaded libcurl into Lisp much as the linker does when you start a C program or common lisp 1load does with a Lisp source file or FASL file We special cased for UNIX machines to always load a particular version the one this tutorial was tested with for those who don t care the defi
99. smatch between the library version with which you tested and the installed library version may cause undefined behavior Implementor s note Maybe some notes should go here about OS X which I know little about stephen 1 Windows programmers may chafe at adding a UNIX specific clause to define foreign library Instead ask why the Windows solution to library incompatibility is include your own version of every library you use with every program Chapter 11 Libraries 99 close foreign library Syntax close foreign library library success Function Arguments and Values library A symbol or an instance of foreign library success A Lisp boolean Description Closes library which can be a symbol designating a library define through define foreign library or an instance of foreign library as returned by load foreign library See Also define foreign library page 101 load foreign library page 105 use foreign library page 108 Chapter 11 Libraries 100 darwin framework directories Syntax darwin framework directories Special Variable Value type A list in which each element is a string a pathname or a simple Lisp expression Initial value A list containing the following in order an expression corresponding to Darwin path Library Frameworks P Library Frameworks and P System Library Frameworks Description The meaning of simple Lisp expression is explained in
100. specialize the translate from foreign generic function in the same manner Define a method that converts C strings to Lisp strings defmethod translate from foreign pointer type my string type foreign string to lisp pointer encoding string type encoding type When a translate to foreign method requires allocation of foreign memory you must also define a free translated object method to free the memory once the foreign object is no longer needed otherwise you ll be faced with memory leaks This generic function is called automatically by CFFI when passing objects to foreign functions Let s do that Free strings allocated by translate to foreign defmethod free translated object pointer type my string type param declare ignore param foreign string free pointer In this specific example we don t need the param argument so we ignore it See free translated object page 51 for an explanation of its purpose and how you can use it A type translator does not necessarily need to convert the value For example one could define a typedef for pointer that ensures in the translate to foreign method that the value is not a null pointer signalling an error if a null pointer is passed This would prevent some pointer errors when calling foreign functions that cannot handle null pointers Chapter 6 Foreign Types 26 Please note these methods are meant as extensible hooks only and you should not call them directl
101. t lt STANDARD METHOD TRANSLATE NAME TO FOREIGN STRING EQL lt Package SOME PACKAGE gt CFFI gt defcfun some xml function someXmlFunction See Also defcfun page 89 translate camelcase name page 94 translate name from foreign page 95 translate underscore separated name page 97 Chapter 10 Functions 97 translate underscore separated name Syntax translate underscore separated name name return value Function Arguments and Values name Either a symbol or a string return value If name is a symbol this is a string and vice versa Description translate underscore separated name is a helper function for specializations of translate name from foreign page 95 and translate name to foreign page 96 It handles the common case of converting between foreign underscore_separated names and lisp names Examples CFFI gt translate underscore separated name some xml function gt gome xml function CFFI gt translate camelcase name some xml function gt SOME XML FUNCTION See Also translate name from foreign page 95 translate name to foreign page 96 translate camelcase name page 94 Chapter 11 Libraries 98 11 Libraries 11 1 Defining a library Almost all foreign code you might want to access exists in some kind of shared library The meaning of shared library varies among platforms but for our purposes we will consider it to include so files on UNIX fra
102. t stores these properties along with the C pointer Unfortunately easy handle is currently just a fancy name for the foreign type pointer the actual pointer object varies from Common Lisp implementation to implementation needing only to satisfy pointerp and be returned from make pointer and friends One solution that would allow us to define a new Lisp structure to represent easy handles would be to write a wrapper around every function that currently takes an easy handle the wrapper would extract the pointer and pass it to the foreign function However we can use type translators to more elegantly integrate this translation into the foreign function calling framework using translate to foreign defclass easy handle pointer initform curl easy init documentation Foreign pointer from curl easy init error buffer initform foreign alloc char count curl error size initial element 0 documentation C string describing last error c strings initform documentation C strings set as options documentation I am a parameterization you may pass to curl easy perform to perform a cURL network protocol request defmethod initialize instance after self easy handle amp key set curl option errorbuffer self slot value self error buffer defun add curl handle cstring handle cstring Add CSTRING to be freed when HANDLE is answering CSTRING car push cstring slot value handle c strings
103. ted the function name to a Lisp friendly name You can specify your own name if you want use curl_global_init your name here as the name argument to defcfun The tutorial goes on to have us allocate a handle For good measure we should also include the deallocator Let s look at these functions CURL curl_easy_init void curl_easy_cleanup CURL handle Advanced users may want to define special pointer types we will explore this possibility later For now just treat every pointer as the same defcfun curl_easy_init pointer defcfun curl_easy_cleanup void easy handle pointer Now we can continue with the tutorial CFFI USER gt defparameter easy handle curl easy init gt EASY HANDLE CFFI USER easy handle lt FOREIGN ADDRESS x09844EE0 gt Note the print representation of a pointer It changes depending on what Lisp you are using but that doesn t make any difference to CFFI 4 5 Setting download options The libcurl tutorial says we ll want to set many options before performing any download actions This is done through curl_easy_setopt CURLcode curl easy setopt CURL curl CURLoption option We ve introduced a new twist variable arguments There is no obvious translation to the defcfun form particularly as there are four possible argument types Because of the way C works we could define four wrappers around curl easy setopt one for each type in this case however we ll use the g
104. terface developed we can finish the defi nition and retrieve http www cliki net CFFI as is done in the tutorial defcfun curl_easy_perform curl code handle easy handle CFFI USER gt with output to string contents let easy write procedure lambda string write string string contents declare special easy write procedure curl easy perform easy handle gt lt DOCTYPE HTML PUBLIC W3C DTD HTML 4 01 EN Now fear comprehensively lt P gt d Unfortunately we can t protect against all non local exits such as returns and throws because unwind protect cannot be used to short circuit a non local exit in Common Lisp due to proposal minimal in ANSI issue EXIT EXTENT Furthermore binding an error handler prevents higher up code from invoking restarts that may be provided under the callback s dynamic context Such is the way of compromise Chapter 4 An Introduction to Foreign Interfaces and CFFI 18 Of course that itself is slightly unwieldy so you may want to define a function around it that simply retrieves a URL I will leave synthesis of all the relevant REPL forms presented thus far into a single function as an exercise for the reader The remaining sections of this tutorial explore some advanced features of CFFI the definition of new types will receive special attention Some of these features are essential for particular foreign function calls some are very helpful when trying to de
105. terfaces and CFFI 4 4 An Introduction to Foreign Interfaces and CFFI Users of many popular languages bearing semantic similarity to Lisp such as Perl and Python are accustomed to having access to popular C libraries such as GTK by way of bindings In Lisp we do something similar but take a fundamentally different approach This tutorial first explains this difference then explains how you can use CFFI a pow erful system for calling out to C and C and access C data from many Common Lisp implementations The concept can be generalized to other languages at the time of writing only CFFI s C support is fairly complete Therefore we will interchangeably refer to foreign functions and foreign data and C functions and C data At no time will the word foreign carry its usual non programming meaning This tutorial expects you to have a working understanding of both Common Lisp and C including the Common Lisp macro system 4 1 What makes Lisp different The following sums up how bindings to foreign libraries are usually implemented in other languages then in Common Lisp Perl Python Java other one implementation languages Bindings are implemented as shared objects written in C In some cases the C code is generated by a tool such as SWIG but the result is the same a new C library that manually translates between the language implementation s objects such as PyObject in Python and whatever C object
106. tiate between normal exits and error exits define condition curl code error error code initarg curl code reader curl error code report lambda c stream format stream libcurl function returned error A curl error code c documentation Signalled when a libcurl function answers a code other than CURLE OK defmethod translate from foreign value type curl code type Raise a CURL CODE ERROR if VALUE a curl code is non zero if zerop value curle ok error curl code error curl code value Chapter 4 An Introduction to Foreign Interfaces and CFFI 19 The heart of this translator is new method translate from foreign By specializing the type parameter on curl code type we immediately modify the behavior of every function that returns a curl code to pass the result through this new method To see the translator in action try invoking a function that returns a curl code You need to reevaluate the respective defcfun form so that it picks up the new curl code definition CFFI USER gt set curl option nosignal easy handle 1 CURLE OK As the result was 0 the new method returned curle ok just as specified I will leave disjoining the separate CURLcodes into condition types and improving the report function as an exercise for you The creation of easy handle cstrings and easy handle errorbuffers as prop erties of easy handles is a kluge What we really want is a Lisp structure tha
107. type stores two symbols passed to the to c and from c arguments When a value is being translated to or from C this type funcalls the respective symbol wrapper types will be typedefs for base type and will inherit its translators if any Here s an example of how the boolean type could be defined in terms of wrapper defun bool c to lisp value not zerop value defun bool lisp to c value if value 1 0 defctype my bool wrapper int from c bool c to lisp to c bool lisp to c convert to foreign nil my bool gt 0 convert from foreign 1 my bool t 6 3 Defining Foreign Types You can define simple C like typedefs through the defctype macro Defining a typedef is as simple as giving defctype a new name and the name of the type to be wrapped Define MY INT as an alias for the built in type INT defctype my int int With this type definition one can for instance declare arguments to foreign functions as having the type my int and they will be passed as integers More complex types CFFI offers another way to define types through define foreign type a thin wrapper macro around defclass As an example let s go through the steps needed to define a my string amp key encoding type First we need to define our type class define foreign type my string type O encoding reader string type encoding initarg encoding actual type pointer Chapter 6 Foreign Types 25 The actual ty
108. ues foreign value The foreign value to convert to a Lisp object type name A symbol naming a foreign type defined by defctype 52 Generic Function lisp value The lisp value to pass in place of foreign value to Lisp code Description This generic function is invoked by CFFI to convert a foreign value to a Lisp value such as when returning from a foreign function passing arguments to a callback function or accessing a foreign variable To extend the CFFI type system by performing custom translations this method may be specialized by EQL specializing type name on a symbol naming a foreign type defined with defctype This method should return the appropriate Lisp value to use in place of the foreign value The results are undefined if the type name parameter is specialized in any way except an EQL specializer on a foreign type defined with defctype Specifically translations may not be defined for built in types See Also Section 6 4 Foreign Type Translators page 25 translate to foreign page 53 free translated object page 51 Chapter 6 Foreign Types 53 translate to foreign Syntax translate to foreign lisp value type name Generic Function foreign value alloc param Arguments and Values lisp value The Lisp value to convert to foreign representation type name A symbol naming a foreign type defined by defctype foreign value The foreign value to pass in place of lisp value to foreign co
109. unction CFFI gt translate camelcase name some xml function special words XML someXMLFunction CFFI gt translate camelcase name someXMLFunction S0ME X M L FUNCTION CFFI gt translate camelcase name someXMLFunction special words XML SOME XML FUNCTION See Also translate name from foreign page 95 translate name to foreign page 96 translate underscore separated name page 97 Chapter 10 Functions 95 translate name from foreign Syntax translate name from foreign foreign name package amp optional Function varp symbol Arguments and Values foreign name A string denoting a foreign function package A Lisp package varp A generalized boolean symbol The Lisp symbol to be used a function name Description translate name from foreign is used by defcfun page 89 to handle the conversion of foreign names to lisp names By default it translates using translate underscore separated name page 97 However you can create specialized methods on this function to make translating more closely match the foreign library s naming conventions Specialize package on some package This allows other packages to load libraries with different naming conventions Examples CFFI gt defcfun someXmlFunction SOMEXMLFUNCTION CFFI gt defmethod translate name from foreign spec string package eql package amp optional varp let name translate camelcase name spec
110. valuates to true That happens for any of the following situations 1 If feature is a symbol present in common lisp features 2 If feature is a list depending on first feature a keyword and All of the feature expressions in rest feature are true or At least one of the feature expressions in rest feature is true not The feature expression second feature is not true 3 Finally if feature is t this load clause is picked unconditionally Upon finding the first true feature the library loader then loads the library The meaning of library designator is described in load foreign library page 105 Functions associated to a library defined by define foreign library e g through defcfun s library option will inherit the library s options The precedence is as follows 1 defcfun foreign funcall specific options 2 load clause options 3 global library options the name and options argument Examples See Section 4 3 Loading foreign libraries page 5 Chapter 11 Libraries 102 See Also close foreign library page 99 load foreign library page 105 Chapter 11 Libraries 103 foreign library directories Syntax foreign library directories Special Variable Value type A list in which each element is a string a pathname or a simple Lisp expression Initial value The empty list Description You should not have to use this variable Most if not all Lisps supported
111. velop a Lispy interface to C 4 11 Defining new types We ve occasionally used the defctype macro in previous sections as a kind of documen tation much what you d use typedef for in C We also tried one special kind of type definition the defcenum type See defcstruct page 33 for a definition macro that may come in handy if you need to use C structs as data However all of these are mostly sugar for the powerful underlying foreign type interface called type translators You can easily define new translators for any simple named foreign type Since we ve defined the new type curl code to use as the return type for various libcurl functions we can use that to directly convert cURL errors to Lisp errors defctype s purpose is to define simple typedef like aliases In order to use type trans lators we must use the define foreign type macro So let s redefine curl code using it define foreign type curl code type O actual type int simple parser curl code define foreign type is a thin wrapper around defclass For now all you need to know in the context of this example is that it does what defctype curl code int would do and additionally defines a new class curl code type which we will take advantage of shortly The CURLcode enumeration seems to follow the typical error code convention of 0 meaning all is well and each non zero integer indicating a different kind of error We can apply that trivially to differen
112. wrappers around primitive foreign function invocations This function is available mostly for inspection of the type translation process and possibly optimization of special cases of your foreign function calls Its behavior is better described under free translated object s documentation Examples CFFI USER gt convert to foreign a boat string lt FOREIGN ADDRESS x097ACDCO gt T CFFI USER gt free converted object string t NIL See Also convert from foreign page 29 convert to foreign page 30 free translated object page 51 Chapter 6 Foreign Types 51 free translated object Syntax free translated object value type name param Generic Function Arguments and Values pointer The foreign value returned by translate to foreign type name A symbol naming a foreign type defined by defctype param The second value if any returned by translate to foreign Description This generic function may be specialized by user code to perform automatic deallocation of foreign objects as they are passed to C functions Any methods defined on this generic function must EQL specialize the type name pa rameter on a symbol defined as a foreign type by the defctype macro See Also Section 6 4 Foreign Type Translators page 25 translate to foreign page 53 Chapter 6 Foreign Types translate from foreign Syntax translate from foreign foreign value type name lisp value Arguments and Val
113. y page 108 106 Chapter 11 Libraries 107 load foreign library error Syntax load foreign library error Condition Type Class precedence list load foreign library error error serious condition condition t Description Signalled when a foreign library load completely fails The exact meaning of this varies depending on the real conditions at work but almost universally the implementation s error message is useless However CFFI does provide the useful restarts retry and use value invoke the retry restart to try loading the foreign library again or the use value restart to try loading a different foreign library designator See also load foreign library page 105 Chapter 11 Libraries 108 use foreign library Syntax use foreign library name Macro Arguments and values name A library designator unevaluated Description See load foreign library page 105 for the meaning of library designator This is intended to be the top level form used idiomatically after a define foreign library form to go ahead and load the library Finally on implementations where the regular evaluation rule is insufficient for foreign library loading it loads it at the required time Examples See Section 4 3 Loading foreign libraries page 5 See also load foreign library page 105 1 Namely CMUCL See use foreign library in libraries lisp for details Chapter 12 Callbacks 109 12 Callback
114. y Use convert to foreign convert from foreign and free converted object instead See Section 4 11 Defining new types page 18 for another example of type translators 6 5 Optimizing Type Translators Being based on generic functions the type translation mechanism described above can add a bit of overhead This is usually not significant but we nevertheless provide a way of getting rid of the overhead for the cases where it matters A good way to understand this issue is to look at the code generated by defcfun Consider the following example using the previously defined my string type CFFI gt macroexpand 1 defcfun foo my string x my string simplified downcased etc defun foo x multiple value bind G2019 PARAM3149 translate to foreign x lt MY STRING TYPE 11ED5A79 gt unwind protect translate from foreign foreign funcall foo pointer G2019 pointer lt MY STRING TYPE 11ED5659 gt free translated object G2019 lt MY STRING TYPE 11ED51A79 gt PARAM3149 In order to get rid of those generic function calls CFFI has another set of extensible generic functions that provide functionality similar to CL s compiler macros expand to foreign dyn expand to foreign and expand from foreign Here s how one could define a my boolean with them define foreign type my boolean type O actual type int simple parser my boolean defmethod expand to foreign value type my bo
115. ype long bools boolean long Booleans that map to C longs See Also define foreign type page 38 Chapter 6 Foreign Types 37 defcenum Syntax defcenum name and options amp body enum list Macro enum list docstring keyword keyword value name and options name name amp optional base type int Arguments and Values name The name of the new enum type docstring A documentation string ignored base type A symbol denoting a foreign type keyword A keyword symbol value An index value for a keyword Description The defcenum macro is used to define foreign types that map keyword symbols to integer values similar to the C enum type If value is omitted its value will either be 0 if it s the first entry or it it will continue the progression from the last specified value Keywords will be automatically converted to values and vice versa when being passed as arguments to or returned from foreign functions respectively The same applies to any other situations where an object of an enum type is expected Types defined with defcenum canonicalize to base type which is int by default Examples defcenum boolean no yes CFFI gt foreign enum value boolean no gt 0 defcenum numbers one 1 two four 4 CFFI gt foreign enum keyword numbers 2 gt TWO See Also foreign enum value page 43 foreign enum keyword page 42 Chapter 6 Foreign Types 38 de
116. ze var is supplied it will be bound to size during body Examples CFFI gt with foreign pointer string 4 size setf mem ref string char 1 size 0 lisp string to foreign Popcorns string size loop for i from 0 below size collect code char mem ref string char i gt P o p Null See Also foreign alloc page 60 foreign free page 59 Chapter 8 Strings 76 8 Strings As with many languages Lisp and C have special support for logical arrays of characters going so far as to give them a special name strings In that spirit CFFI provides special support for translating between Lisp and C strings The string type and the symbols related below also serve as an example of what you can do portably with CFFI were it not included you could write an equally functional strings lisp without referring to any implementation specific symbols Chapter 8 Strings 77 default foreign encoding Syntax default foreign encoding Special Variable Value type A keyword Initial value utf 8 Description This special variable holds the default foreign encoding Examples CFFI gt default foreign encoding utf 8 CFFI gt foreign funcall strdup string encoding utf 16 foo string ur CFFI gt let default foreign encoding utf 16 foreign funcall strdup string encoding utf 16 foo string foo See also Section 6 2 Other Types page 23 string type

Download Pdf Manuals

image

Related Search

Related Contents

PRIMERGY TX150 S7 Server  32269 Hydro HGRS200 E-03-499 FINAL2  Samsung Full HD Monitor S22D300HY LED (22") Korisničko uputstvo  HoMedics PAR-300 User's Manual  LG MS500 Specification Sheet  kit multímetro pro manual de instruções    Bedienungsanleitung • DMX MASTER I & II  La Crosse Technology WT-8005U User's Manual  STERLING 442421-0 Installation Guide  

Copyright © All rights reserved.
Failed to retrieve file