Avoid warning from C++ compiler
[cffi.git] / doc / allegro-internals.txt
blob64c0d7ecb107b719e9ca52eb285f8d64914f77d7
1 July 2005
2 These details were kindly provided by Duane Rettig of Franz.
4 Regarding the following snippet of the macro expansion of
5 FF:DEF-FOREIGN-CALL:
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 * *)))
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)."
24 This is the code that generates what the compiler expects to see:
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)))
38 Thus generating something like:
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                       )))
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.
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:
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
72 (defconstant ep-flag-tramp-calls #x70) ; Make calls through special trampolines
73 (defconstant ep-flag-tramp-shift 4)
75 (defconstant ep-flag-variable-address #x100) ; Entry-point contains address of C var
76 (defconstant ep-flag-strings-convert #x200)      ; Convert strings automatically
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
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.
86 Some docs for entry-vec are:
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.
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   )
110 [...]
113 Regarding the arguments to SYSTEM::FF-FUNCALL:
114   '(:int (integer * *)) argN
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[...]"
121 Getting the alignment:
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    ...)