allegro-internals.txt - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) LICENSE --- allegro-internals.txt (5245B) --- 1 July 2005 2 These details were kindly provided by Duane Rettig of Franz. 3 4 Regarding the following snippet of the macro expansion of 5 FF:DEF-FOREIGN-CALL: 6 7 (SYSTEM::FF-FUNCALL 8 (LOAD-TIME-VALUE (EXCL::DETERMINE-FOREIGN-ADDRESS 9 '("foo" :LANGUAGE :C) 2 NIL)) 10 '(:INT (INTEGER * *)) ARG1 11 '(:DOUBLE (DOUBLE-FLOAT * *)) ARG2 12 '(:INT (INTEGER * *))) 13 14 " 15 ... in Allegro CL, if you define a foreign call FOO with C entry point 16 "foo" and with :call-direct t in the arguments, and if other things are 17 satisfied, then if a lisp function BAR is compiled which has a call to 18 FOO, that call will not go through ff-funcall (and thus a large amount 19 of argument manipulation and processing) but will instead set up its 20 arguments directly on the stack, and will then perform the "call" more 21 or less directly, through the "entry vec" (a small structure which 22 keeps track of a foreign entry's address and status)." 23 24 This is the code that generates what the compiler expects to see: 25 26 (setq call-direct-form 27 (if* call-direct 28 then `(setf (get ',lispname 'sys::direct-ff-call) 29 (list ',external-name 30 ,callback 31 ,convention 32 ',returning 33 ',arg-types 34 ,arg-checking 35 ,entry-vec-flags)) 36 else `(remprop ',lispname 'sys::direct-ff-call))) 37 38 Thus generating something like: 39 40 (EVAL-WHEN (COMPILE LOAD EVAL) 41 (SETF (GET 'FOO 'SYSTEM::DIRECT-FF-CALL) 42 (LIST '("foo" :LANGUAGE :C) T :C 43 '(:INT (INTEGER * *)) 44 '((:INT (INTEGER * *)) 45 (:FLOAT (SINGLE-FLOAT * *))) 46 T 47 2 ; this magic value is explained later 48 ))) 49 50 " 51 (defun determine-foreign-address (name &optional (flags 0) method-index) 52 ;; return an entry-vec struct suitable for the foreign-call of name. 53 ;; 54 ;; name is either a string, which is taken without conversion, or 55 ;; a list consisting of a string to convert or a conversion function 56 ;; call. 57 ;; flags is an integer representing the flags to place into the entry-vec. 58 ;; method-index, if non-nil, is a word-index into a vtbl (virtual table). 59 ;; If method-index is true, then the name must be a string uniquely 60 ;; represented by the index and by the flags field. 61 62 Note that not all architectures implement the :method-index argument 63 to def-foreign-call, but your interface likely won't support it 64 anyway, so just leave it nil. As for the flags, they are constants 65 stored into the entry-vec returned by d-f-a and are given here: 66 67 (defconstant ep-flag-call-semidirect 1) ; Real address stored in alt-address slot 68 (defconstant ep-flag-never-release 2) ; Never release the heap 69 (defconstant ep-flag-always-release 4) ; Always release the heap 70 (defconstant ep-flag-release-when-ok 8) ; Release the heap unless without-interrupts 71 72 (defconstant ep-flag-tramp-calls #x70) ; Make calls through special trampolines 73 (defconstant ep-flag-tramp-shift 4) 74 75 (defconstant ep-flag-variable-address #x100) ; Entry-point contains address of C var 76 (defconstant ep-flag-strings-convert #x200) ; Convert strings automatically 77 78 (defconstant ep-flag-get-errno #x1000) ;; [rfe5060]: Get errno value after call 79 (defconstant ep-flag-get-last-error #x2000) ;; [rfe5060]: call GetLastError after call 80 ;; Leave #x4000 and #x8000 open for expansion 81 82 Mostly, you'll give the value 2 (never release the heap), but if you 83 give 4 or 8, then d-f-a will automatically set the 1 bit as well, 84 which takes the call through a heap-release/reacquire process. 85 86 Some docs for entry-vec are: 87 88 ;; -- entry vec -- 89 ;; An entry-vec is an entry-point descriptor, usually a pointer into 90 ;; a shared-library. It is represented as a 5-element struct of type 91 ;; foreign-vector. The reason for this represntation is 92 ;; that it allows the entry point to be stored in a table, called 93 ;; the .saved-entry-points. table, and to be used by a foreign 94 ;; function. When the location of the foreign function to which the entry 95 ;; point refers changes, it is simply a matter of changing the value in entry 96 ;; point vector and the foreign call code sees it immediately. There is 97 ;; even an address that can be put in the entry point vector that denotes 98 ;; a missing foreign function, thus lookup can happen dynamically. 99 100 (defstruct (entry-vec 101 (:type (vector excl::foreign (*))) 102 (:constructor make-entry-vec-boa ())) 103 name ; entry point name 104 (address 0) ; jump address for foreign code 105 (handle 0) ; shared-lib handle 106 (flags 0) ; ep-* flags 107 (alt-address 0) ; sometimes holds the real func addr 108 ) 109 110 [...] 111 " 112 113 Regarding the arguments to SYSTEM::FF-FUNCALL: 114 '(:int (integer * *)) argN 115 116 "The type-spec is as it is given in the def-foreign-call 117 syntax, with a C type optionally followed by a lisp type, 118 followed optionally by a user-conversion function name[...]" 119 120 121 Getting the alignment: 122 123 CL-USER(2): (ff:get-foreign-type :int) 124 #S(FOREIGN-FUNCTIONS::IFOREIGN-TYPE 125 :ATTRIBUTES NIL 126 :SFTYPE 127 #S(FOREIGN-FUNCTIONS::SIZED-FTYPE-PRIM 128 :KIND :INT 129 :WIDTH 4 130 :OFFSET 0 131 :ALIGN 4) 132 ...)