4.1 The Foreign Function Interface
copy-foreign-pointer
foreign-pointer&key :static :malloc :alignment
copy-foreign-pointer
creates a new foreign pointer object of the same type as the specified argument and that points at a copy of the foreign storage pointed at by the argument.
:malloc
keyword argument has a non-nil
value, the storage is allocated by the functionmalloc-foreign-pointer
.:alignment
keyword argument is passed tomalloc-foreign-pointer
. The default value of the:alignment
keyword argument is 1.make-foreign-pointer
allocates the storage.:static
and the:alignment
keyword arguments are passed tomake-foreign-pointer
.
> (def-foreign-struct test (a :type :signed-32bit) (b :type :double-float)) TEST> (setq *fp1* (make-test :a 99 :b 1.23)) #<Foreign-Pointer 79C028 (:POINTER TEST)>
> (test-a *fp1*) 99 > (test-b *fp1*) 1.23
> (setq *fp2* (copy-foreign-pointer *fp1*)) #<Foreign-Pointer 79C038 (:POINTER TEST)>
> (test-a *fp2*) 99
> (test-b *fp2*) 1.23
make-foreign-pointer
,
Syntax:def-foreign-callable
name-and-options ({arg-description}*){declaration | documentation}*
{form}*
name-and-options::= function-name| (function-name {option}*)
option::= (:language
language)| (
:name
foreign-name)| (
:return-type
return-type)
arg-description::= (arg-name foreign-type)
def-foreign-callable
defines a Lisp function that can be called from a function defined by a language other than Lisp, that is, by a foreign function.
def-foreign-callable
is a symbol that is specified by the function-name argument and that associates a foreign function name with a Lisp function name. Once the association is specified, you can use the foreign function to call the resulting Lisp function from outside Lisp.
:language
language
:c
, which is the default value. The Section 4.4 shows the call disciplines used when you pass foreign data to Lisp functions, and vice versa.
:name
foreign-namedef-foreign-callable
.
*lisp-symbol-to-foreign-string-method*
is a function of two arguments, the function is called with the symbol and the language as arguments. If the function returns a string, that string is used as the symbol name.:return-type
foreign-type
declare
.
function
.
def-foreign-callable
must be evaluated before the foreign file is loaded with the functionload-foreign-file
. If a foreign file is loaded before the applicabledef-foreign-callable
forms have been evaluated (or have been loaded from a compiled file), you can use the functionreload-foreign-files
to reload all foreign files and thus complete the necessary linkages. There is no order dependency on uses of the macrodef-foreign-function
with the functionload-foreign-file
.
; This example assumes that the file "callback.c" contains the ; following code, that this file has been compiled using ; "cc -c callback.c". ; ; int c_function (value, string) ; int value; ; char *string; ; { ; return ( c_to_lisp_function(value, string) ) ; ; }; Load the foreign-code. > (load-foreign-files "callback.o") ;;; Loading foreign object file "callback.o" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/tmp_mnt/net/cos2/sparccc/ ;;; SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/ucblib/libucb.a" ;;; Warning: The following foreign symbols are undefined: (c_to_lisp_function) NIL
; Note that the foreign-function c_to_lisp_function is not yet ; defined. You can define it from Lisp by using def-foreign- ; callable. > (def-foreign-callable (c-to-lisp-function (:return-type :signed-32bit)) ((value :signed-32bit) (string :simple-string)) (print string) (* value 3)) C-TO-LISP-FUNCTION
; Verify that c_to_lisp_function is now defined. > (foreign-undefined-symbol-names) NIL
; Next define a way to call the foreign-function c_function from ; this is a test Lisp. > (def-foreign-function (test-callback (:name "c_function") (:return-type :signed-32bit)) (value :signed-32bit) (string :simple-string)) TEST-CALLBACK
; Test the defined functions. > (test-callback 23 "this is a test string") "this is a test string" 69
; To see what happened in more detail, trace #'print and #'*. > (trace print *) (PRINT *)
> (test-callback 23 "this is a test string") 1 Enter PRINT "this is a test string" "this is a test string" 1 Exit PRINT "this is a test string" 1 Enter * 23 3 1 Exit * 69 69
> (untrace) (PRINT *)
def-foreign-callable
Syntax:def-foreign-function
name-and-options {documentation}*{arg-description}*
[
&optional
{arg-description}+][
&rest
{arg-description}+][
&key
{arg-description}+]
name-and-options::= function-name|(function-name {option}*)
option::= (:language
language)|(
:name
foreign-name)|(
:return-type
return-type)|(
:max-rest-args
value)
arg-description::= arg-name|(arg-name foreign-type)
|((arg-name default-value) foreign-type)
def-foreign-function
creates a Lisp function that calls a foreign function, or a function defined by a language other than Lisp. The macro converts Lisp arguments to the appropriate foreign data type before it calls the foreign function. The value returned by the foreign function is converted to a Lisp data type.
def-foreign-function
create interpreted Lisp functions, and compiled calls create compiled Lisp functions.
def-foreign-function
is a symbol that is specified by the function-name argument and that associates a Lisp function name with an appropriate foreign function name. Once the association is specified, you can use the resulting Lisp function to call the foreign function from within Lisp.
:language
language:fortran
,:c
, or :pascal
; the default value is:c
. The Section 4.4 shows the calling conventions used when you pass foreign data to Lisp functions, and vice versa.
:name
foreign-name
*lisp-symbol-to-foreign-string-method*
is a function of two arguments, the function is called with the symbol and the language as arguments. If the function returns a string, that string is used as the symbol name.def-foreign-function
is used.
:return-type
foreign-type
:max-rest-args
value&rest
arguments that you can pass as arguments to the foreign function. The value that you specify must be an integer that is greater than or equal to 0 and that is less than or equal to the machine-specific limit for the number of arguments that a function can take; the machine-specific limit must be at least 100. The default value is 10. If the foreign function does not take&rest
arguments, this option has no effect.
function
.
&optional
,&rest
, or&key
. You can list this argument with a default-value if you supply the optional argument foreign-type.
:arbitrary
, which indicates that the coercion is based on the specified:language
option.
:array
,:string
,:simple-string
, and:simple-vector-type
change the argument passed by the Lisp function.
f_init
, which is defined in the FORTRAN libraries. But when you use isolated compiled FORTRAN functions, as in the Foreign Function Interface, you must explicitly perform the initialization. Thus, you should load the initialization function and evaluate it before evaluating the FORTRAN functions, as the following example shows:
> (def-foreign-function (f_init (:language :fortran) (:return-type :null) (:name "f_init"))) F_INIT> (load-foreign-libraries nil '("-lV77" "-lF77" "-lM77" "-lm" "-lc")) ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a"+ ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" T
> (f_init) NIL
with-static-area
or symbols that have been freshly created in a package by the Common Lisp functionintern
; note that the functionread
calls intern
. If dynamic data are passed to foreign functions, the results are unpredictable. See the reference page for stationary-object-p
for more information.
;; In the first example, call a FORTRAN library function that ;; takes a string of length 24 and writes the current date in it. > (def-foreign-function (fdate (:language :fortran) (:return-type :null)) (name :simple-string)) FDATE> (load-foreign-libraries nil '("-lF77" "-lM77" "-lV77" "-lm" "-lc")) ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libF77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libM77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0.1/libV77.a" ;;; Reading library file "/opt/SUNWspro/SC2.0/cg89/libm.a" ;;; Reading library file "/usr/lib/libc.a" T
> (setq date-string (with-static-area (make-string 24 :initial-element #\-))) "------------------------"
> (fdate date-string) NIL
> date-string "Tue Jan 5 14:29:49 PST
;;; The next example uses Pascal. > (def-foreign-function (pcos (:language :pascal) (:name "cos") (:return-type :double-float)) (x :double-float))
> (load-foreign-libraries nil '("-lpc" "-lm" "-lc")) > (pcos pi) ;;; The last example shows how the Foreign Function Interface ;;; works in C. > (def-foreign-function (get-c-env (:name "getenv") (:return-type :simple-string)) (name :pointer)) GET-C-ENV
> (setq name (malloc-foreign-pointer :type '(:pointer (:array :character (100))))) #<Foreign-Pointer 6F7180 (:POINTER (:ARRAY :CHARACTER (100)))>
> (load-foreign-libraries nil '("-lm" "-lc")) T
> (setf (foreign-string-value name) "SHELL") "SHELL"
> (get-c-env name) "/bin/csh"
> (setf (foreign-string-value name) "nonsense") "nonsense"
> (get-c-env name) NIL
def-foreign-callable
, load-foreign-files
, stationary-object-p
;with-static-area
(in The User's Guide)
Syntax:def-foreign-struct
name-and-options {slot-decription}*
name-and-options::= structure-name
|(structure-name (:alignment
alignment-info))
structure-name::= symbol
alignment-info::= (:modulus value
)|(:modulus
value:remainder
value)
slot-description::= (slot-name:type
slot-type-name)|(slot-name
:type
slot-type-name :overlays
previous-slot-name)|(slot-name
:type
slot-type-name :offset
value)
slot-name::= symbol
slot-type-name::= 1array-element-type-name|field-type-name
array-element-type-name::= primitive-array-element-type-name |previously-defined-structure-type-name
|(
:array
array-element-type-name array-dimension-list
)|(
:array
array-element-type-name array-dimension-list
[array-discipline])
primitive-array-element-type-name::= :character
|:signed-8bit
|:unsigned-8bit
|:signed-16bit
|:unsigned-16bit
|:signed-32bit
|:unsigned-32bit
|:single-float
|:double-float
| (:[pointer slot-type-name
)
field-type-name::= (:field
size position)|(
:signed-field
size position)|(
:bit-field
size position)|(
:signed-bit-field
size position)
array-discipline::= :row-major
|:column-major
def-foreign-struct
defines structures within Lisp that are determined by other languages. Each structure has a fixed number of named components, which are called slots.
def-foreign-struct
is a symbol that names the foreign structure. The following functions are automatically defined to operate on instances of the foreign structure:-p
tests membership in the foreign structure type.setf
with these access functions to destructively modify the contents of the slot.make-structure-name
creates and returns new instances of the foreign structure type.:alignment
keyword option. The symbol names the type of foreign structure being defined. The alignment-info argument to the keyword:alignment
is a list of the following keywords and arguments::modulus
keyword argument is an integer between 1 and 4095 inclusive. The default value is the least common multiple of the moduli for the slot types of the structure.:remainder
keyword argument is an integer whose lowest value is 0 and whose highest value is 1 less than the value of the:modulus
keyword argument. The default value is 0.:remainder
argument modulo the:modulus
argument.
:overlays
keyword option as part of the slot-description argument if you want a slot to begin at the same machine address as a previously defined slot. The:offset
keyword argument is any nonnegative fixnum; it specifies the number of bytes from the beginning address of the structure that are skipped over before the slot begins.
:overlays
and:offset
options::offset
argument, you cannot use that slot as an:overlays
argument.:offset
argument must be consistent with the alignment requirements of the structure being defined and with the slot type.:overlays
argument except for slots with specified offsets.:overlays
argument for a slot whose alignment requirements are incompatible with the slot that it overlays.:field
and:signed-field
keyword options for field-type-name take two arguments. The size argument is a positive fixnum between 1 and 32 inclusive; there are 32 bits in a full machine word. The position argument is a nonnegative fixnum; the sum of the value specified for this argument and the value of the size argument must not exceed 32.
:bit-field
and:signed-bit-field
keyword options are like the:field
and:signed-field
options, except that a:bit-field
type fits into the smallest possible number of bytes. That is, the foreign type size of:bit-field
or:signed-bit-field
is(ceiling (+ type position) bits-per-byte)
.
:array
keyword option is used to make a recursive reference to the array element type specified as its first argument. Its second argument, array-dimension-list, is a list of nonnegative integers that specify the size of each of the dimensions of the array. The default value of the array-discipline argument is:row-major
; in Common Lisp, the elements of a multidimensional array are stored in row-major order.
> (def-foreign-struct (example-struct (:alignment (:modulus 4 :remainder 2))) (slot-a :type :unsigned-32bit) (slot-b :type :signed-16bit)) EXAMPLE-STRUCT
def-foreign-synonym-type
, foreign-value
, free-foreign-pointer
, make-foreign-pointer
, malloc-foreign-pointer
, foreign-aref
, typed-foreign-aref
, undefine-foreign-type
def-foreign-synonym-type
atomic-type-name previously-defined-type-name
def-foreign-synonym-type
creates a synonym type for a previously defined type; that is, it associates a new name with an existing type.
;;; This example makes the symbol 'test-array a synonym for the ;;; list '(:array :character (2 3 4) :column-major).> (def-foreign-synonym-type test-array (:array :character (2 3 4) :column-major)) #<Foreign-Type (:ARRAY :CHARACTER (2 3 4) :COLUMN-MAJOR) 9B5D06>
; The following examples use the :enumeration, :set, and :packed- ; array foreign types, which correspond to Pascal data types.
> (def-foreign-synonym-type primary_colors (:enumeration (red yellow blue))) #<Foreign-Type (:ENUMERATION (RED YELLOW BLUE)) 9B774E>
> (setq color1 (make-foreign-pointer :type '(:pointer primary_colors))) #<Foreign-Pointer 75005C (:POINTER PRIMARY_COLORS)>
> (foreign-value color1) RED
> (symbol-value 'red) 0
> (def-foreign-synonym-type grades-type (:set :character)) #<Foreign-Type (:SET :CHARACTER) 9B896E>
> (setq grade1 (make-foreign-pointer :type '(:pointer grades-type))) #<Foreign-Pointer 750064 (:POINTER GRADES-TYPE)>
> (setf (foreign-value grade1) '(#\A #\B #\C #\D #\E #\F)) (#\A #\B #\C #\D #\E #\F)
> (foreign-value grade1) (#\A #\B #\C #\D #\E #\F)
> (def-foreign-synonym-type packed-array-3 (:packed-array 3 (10))) #<Foreign-Type (:PACKED-ARRAY (:FIELD 3 0) (10)) 9B98CE>
undefine-foreign-type
defined-foreign-type-p
type-name
defined-foreign-type-p
is true if the type-name argument specifies a currently defined foreign type; otherwise, it is false.
> (def-foreign-struct test-type (slot-1 :type :signed-32bit)) TEST-TYPEforeign-aref> (defined-foreign-type-p 'test-type) T
Function
foreign-aref
foreign-vector&rest
indices
typed-foreign-aref
foreign-type foreign-vector&rest
indices
foreign-aref
andtyped-foreign-aref
provide Lisp access to arrays that are defined in other languages.
typed-foreign-aref
also checks that the foreign array is of the specified type.
typed-foreign-aref
is an optimized version offoreign-aref
that provides access as fast as the Common Lisp functionaref
when the array type has been declared. You must use the production mode of the Compiler to benefit from this optimization.
:array
. You can create the foreign pointer with the functionsmake-foreign-pointer
,malloc-foreign-pointer
, or by combining the primitive type:pointer
with the primitive type:array
.
typed-foreign-aref
is a previously defined foreign type. It can be one of the predefined types listed in Section 4.3, or any type derived from a predefined type. It is an error if the foreign-vector argument is not of the type specified in the foreign-type argument.
setf
with these functions to destructively modify a foreign array element. An error is signaled if you attempt to set the foreign array element to a value that is illegal for its type.
(def-foreign-synonym-type array-example-type (:pointer (:array :signed-16bit (10)))) #<Foreign-Type (:POINTER (:ARRAY :SIGNED-16BIT (10))) 9BAF26>foreign-pointer-address> (setq example-array (make-foreign-pointer :type 'array-example-type)) #<Foreign-Pointer 75008C (:POINTER (:ARRAY :SIGNED-16BIT (10)))>
> (dotimes (i 10) (setf (foreign-aref example-array i) i)) NIL
> (foreign-aref example-array 4) 4
> (typed-foreign-aref 'array-example-type example-array 7) 7
Function foreign-type-remainder Function
foreign-pointer-address
foreign-pointer
foreign-pointer-p
foreign-pointer
foreign-pointer-type
foreign-pointer
foreign-typep
foreign-pointer foreign-type
foreign-type-modulus
foreign-type
foreign-type-remainder
foreign-type
foreign-type-size
foreign-type
foreign-pointer-address
,foreign-pointer-p
,foreign-pointer-type
, andforeign-typep
return information about the specified foreign pointer.
foreign-type-modulus
,foreign-type-remainder
, andforeign-type-size
return information about the specified foreign type.
:pointer
.
foreign-pointer-address
returns the integer starting address of the object being pointed at by the foreign-pointer argument. You can use the Common Lisp macrosetf
with this function to destructively modify the address of the object being pointed at.
foreign-pointer-p
is true if its foreign-pointer argument is of type :pointer
; otherwise, it is false.
foreign-pointer-type
returns the type of the foreign-pointer argument. You can use the Common Lisp macrosetf
with this function to destructively modify the foreign-pointer argument.
foreign-typep
is true if the foreign-pointer argument is of the specified type; otherwise, it is false.
foreign-type-modulus
returns the alignment modulus of the specified foreign type. The functionforeign-type-remainder
returns the alignment remainder of the specified foreign type. Foreign types that use alignment are constructed to start at a machine address that is congruent to the alignment remainder modulo the alignment modulus.
foreign-type-size
returns the unit size of the specified foreign type.
> (setq example-pointer (make-foreign-pointer :type '(:pointer :signed-32bit))) #<Foreign-Pointer 7500AC (:POINTER :SIGNED-32BIT)>> (foreign-pointer-address example-pointer) 7667884
> (foreign-pointer-p example-pointer) T
> (foreign-pointer-type example-pointer) #<Foreign-Type (:POINTER :SIGNED-32BIT) 9BD236>
> (foreign-typep example-pointer '(:pointer :signed-32bit)) T
> (foreign-type-modulus :unsigned-8bit) 1
> (foreign-type-remainder :unsigned-8bit) 0
> (foreign-type-size :unsigned-8bit) 1
def-foreign-struct
foreign-size-of
foreign-pointer-or-type
foreign-size-of
returns an integer value whose meaning depends on the specified argument:foreign-type-size
.
my-type
is the name of a foreign type such that the value returned by the functionforeign-type-size
formy-type
is 12. Assume also thatmy-type-pointer
is of type(:pointer my-type)
. In this case, the value returned byforeign-size-of
for bothmy-type
and formy-type-pointer
is 12.
(:pointer my-type)
is 4, not 12. In other words, even though the value returned by(foreign-pointer-type my-type-pointer)
is a type whose name is'(:pointer my-type)
, the type of the foreign pointer object is not the type of the foreign storage that the object points at.
foreign-type-size
foreign-string-value
foreign-pointer
foreign-string-value
returns a copy of the string pointed at by the specified foreign pointer.
:pointer
and must point to a character object or an array of character objects.
setf
with this function to modify the string pointed at by the foreign-pointer argument.
;;; This example assumes that the file "string-test.c" contains ;;; the following code and that this file has been compiled using ;;; "cc -c string-test.c". ;;; ;;; char *test_string = "This is a test-string."; ;;; char *string_function () ;;; { ;;; return ( test_string ); ;;; }foreign-undefined-symbol-names Function;; Load the foreign-code. > (load-foreign-files "string-test.o") ;;; Loading foreign object file "string-test.o" T
;; Define a function to look at the test-string. > (def-foreign-function (string-function (:return-type :simple-string))) STRING-FUNCTION
> (string-function) "This is a test-string."
;; Define another foreign function that calls the same code to ;; return a foreign-pointer of type (:pointer :character). > (def-foreign-function (string-function-2 (:name "string_function") (:return-type (:pointer :character)))) STRING-FUNCTION-2
> (setq str-ptr (string-function-2)) #<Foreign-Pointer 6DC958 (:POINTER :CHARACTER)>
;; The foreign value "str-ptr" points at the C string ;; "test_string". > (foreign-string-value str-ptr) "This is a test-string."
;; You can change the string if you are careful to put in another ;; string of length at most that of the original one; this change ;; is then reflected in the foreign function #'string-function. > (setf (foreign-string-value str-ptr) "This is a changed string.") "This is a changed string."
> (foreign-string-value str-ptr) "This is a changed string."
> (string-function) "This is a changed string."
;;; The value returned by FOREIGN-STRING-VALUE depends on the ;;; type of the object being pointed at. If the foreign pointer ;;; points to a character, FOREIGN-STRING-VALUE copies the ;;; foreign characters, starting at the one pointed to, into a ;;; Lisp string. If the foreign pointer points to an array of ;;; characters, FOREIGN-STRING-VALUE copies all the characters ;;; in the foreign array into a Lisp string. The result of using ;;; SETF with FOREIGN-STRING-VALUE depends on the foreign ;;; pointer's type similarly. The following example demonstrates ;;; this difference. It first creates and initializes a foreign ;;; array of characters and two foreign pointers that refer to it.
> (setq array-8 (malloc-foreign-pointer :type '(:pointer (:array :character (8))))) #<Foreign-Pointer 6F6090 (:POINTER (:ARRAY :CHARACTER (8)))>
> (setq array-4 (make-foreign-pointer :type '(:pointer (:array :character (4))) :address (foreign-pointer-address array-8))) #<Foreign-Pointer 6F6090 (:POINTER (:ARRAY :CHARACTER (4)))>
> (setf (foreign-string-value array-8) "12345678") "12345678"
;; The function treats array-8 differently from array-4. > (foreign-string-value array-8) "12345678"
> (foreign-string-value array-4) "1234"
;; Using SETF with FOREIGN-STRING-VALUE manipulates the foreign ;; storage referred to by these two pointers differently. > (setf (foreign-string-value array-4) "abcd") "abcd"
> (foreign-string-value array-8) "abcd5678"
;; Since FOREIGN-STRING-VALUE always uses the whole character ;; array, the result of the following expressions is not ;; surprising. This property is used to null-terminate the ;; foreign sequence of characters returned by MALLOC-FOREIGN- ;; STRING as defined in the example in ;; Section 4.1.1 > (setf (foreign-string-value array-8) "A") "A"
> (foreign-string-value array-8) "A^@^@^@^@^@^@^@"
;; Now that the character array pointed to by both of these ;; foreign pointers can be treated as a null-terminated sequence ;; of characters, define a foreign pointer that does so. > (setq char-seq (make-foreign-pointer :type '(:pointer :character) :address (foreign-pointer-address array-8))) #<Foreign-Pointer 6F6090 (:POINTER :CHARACTER)>
> (foreign-string-value char-seq) "A"
;; Note that using SETF with FOREIGN-STRING-VALUE on (:pointer ;; :character) overwrites null bytes. You must ensure that the ;; foreign storage referred to has enough space for the new value. > (setf (foreign-string-value char-seq) "12345") "12345"
> (foreign-string-value array-8) "12345^@^@^@"
foreign-undefined-symbol-names
foreign-undefined-symbol-names
returns a list of the names of foreign symbols that are not currently associated with any foreign code or data.
;; Note that there are NO undefined foreign symbols. > (foreign-undefined-symbol-names) NIL;; Create an undefined foreign symbol. > (def-foreign-function (foreign-undefined-function (:name "JUNK-FUNCTION"))) FOREIGN-UNDEFINED-FUNCTION
> (foreign-undefined-symbol-names) ("JUNK-FUNCTION")
;; Get rid of the undefined foreign symbol. > (unintern-foreign-symbol "JUNK-FUNCTION") T
> (foreign-undefined-symbol-names) NIL
unintern-foreign-symbol
foreign-value
foreign-pointer
foreign-value
evaluates its foreign-pointer argument as follows:setf
with this function to destructively modify the value pointed at by the foreign-pointer argument.
> (setq example-pointer (make-foreign-pointer :type '(:pointer :signed-32bit))) #<Foreign-Pointer 7500BC (:POINTER :SIGNED-32BIT)>> (setf (foreign-value example-pointer) -123) -123
> (foreign-value example-pointer) -123
;;; The :bit-field type is similar to the :field type, except that ;;; the foreign type size of a :bit-field type is ;;; (ceiling (+ <size> <position>) <bits-per-byte>). > (setq fp-bit-field (make-foreign-pointer :type '(:pointer (:bit-field 13 3)))) #<Foreign-Pointer 79C038 (:POINTER (:BIT-FIELD 13 3))>
> (setq fp-16bit (make-foreign-pointer :type '(:pointer :unsigned-16bit) :address (foreign-pointer-address fp-bit-field))) #<Foreign-Pointer 79C038 (:POINTER :UNSIGNED-16BIT)>
> (setf (foreign-value fp-bit-field) 1234) 1234
> (foreign-value fp-bit-field) 1234
> (foreign-value fp-16bit) 9872
> (ldb (byte 13 3) (foreign-value fp-16bit)) 1234
> (foreign-type-size '(:bit-field 13 3)) 2
make-foreign-pointer
, malloc-foreign-pointer
Function foreign-variable-address Function
foreign-variable-pointer Function
foreign-variable-p
string
foreign-variable-address
string
foreign-variable-pointer
string
foreign-variable-p
,foreign-variable-address
, and foreign-variable-pointer
return information about the active global foreign variable with the name specified in the string argument. A foreign variable is foreign storage that has a name.foreign-variable-p
is true if an active global foreign variable with the specified name exists; otherwise, it is false.foreign-variable-address
returns the integer starting address of the active global foreign variable with the specified name.foreign-variable-pointer
returns the foreign pointer that points at the active global foreign variable with the specified name."var"
for C variables namedvar
"var_"
for FORTRAN variables namedvar
disksave
, foreign pointers returned by the functionforeign-variable-pointer
are preserved.
;; The foreign variable "write" is a Unix system-call. > (foreign-variable-p "write") :TEXT> (foreign-variable-address "write") 6315640
> (foreign-variable-pointer "write") #<Foreign-Pointer write 605E78>
;;; UNIX system calls that fail set errno to an error-specific ;;; positive integer; they do not clear it if no error occurs and ;;; instead indicate that an error has occurred with an otherwise ;;; impossible return value, usually -1. The values of errno are ;;; described in INTRO(2) and <errno.h> in the UNIX manual pages ;;; (usually available on line); each system call description ;;; mentions the errors that it can encounter. The following Lisp ;;; code manipulates the foreign variable errno.
;; Rather than create a new foreign pointer every time errno is ;; accessed, reuse a foreign pointer to errno.
> (let ((errno-ptr (foreign-variable-pointer "errno"))) ;; The Lisp function errno returns the current value of the ;; foreign variable errno. (defun errno () (foreign-value errno-ptr)) ;; The function reset-errno changes the value of the foreign ;; variable errno. By default, it resets the value to 0. It ;; returns errno's previous value. (defun reset-errno (&optional (n 0)) (check-type n unsigned-byte) (prog1 (foreign-value errno-ptr) (setf (foreign-value errno-ptr) n))) ) RESET-ERRNO
;;; UNIX also provides sys_errlist, a vector of message strings ;;; that describes the possible values of errno. The foreign ;;; variable sys_nerr contains the number of entries in this ;;; vector.
;; Again, rather than create a new foreign pointer every time the ;; message string vector is accessed, the foreign pointers are ;; reused. > (let* ((sys_nerr (foreign-value (make-foreign-pointer :type '(:pointer :signed-32bit) :address (foreign-variable-address "sys_nerr")))) (error-strings (make-foreign-pointer :type '(:pointer (:array (:pointer :character) (,sys_nerr))) :address (foreign-variable-address "sys_errlist")))) ;; Like the Lisp interface to errno that was defined ;; previously, the Lisp interface to the sys_errlist that is ;; being defined is different from the UNIX interface. The ;; function sys_errlist returns a Lisp string describing the ;; error-code, which defaults to the most recent UNIX error. ;; If error-code is not in the foreign variable sys_errlist, ;; the Lisp function returns "Unknown error"; this behavior ;; mirrors that of the LIBC function PERROR(3), which is used ;; to print error messages. (Since PERROR(3) does I/O, it ;; should not be used from Lisp.) (defun sys_errlist (&optional (error-code (errno))) (check-type error-code unsigned-byte) (if (< error-code sys_nerr) (foreign-string-value (foreign-aref error-strings error-code)) "Unknown error")) ) SYS_ERRLIST
;;; First clear any residual errors and see what the error message ;;; for no error is. > (reset-errno) 22
> (sys_errlist) "Error 0"
;; Now cause an error by using the STAT function defined in ;; Section 4.1.4 > (stat "there is no file with this name") NIL
> (sys_errlist) "No such file or directory"
> (errno) 2
foreign-undefined-symbol-names
Function
free-foreign-pointer
foreign-pointer
free-foreign-pointer
uses the library function"free"
to free the foreign storage being pointed at by the specified foreign pointer; the foreign pointer must have been created with the functionmalloc-foreign-pointer
.
"malloc"
at any time.
:pointer
.
malloc-foreign-pointer
Variable
*lisp-symbol-to-foreign-string-method*
*lisp-symbol-to-foreign-string-method*
is used by the macrosdef-foreign-callable
anddef-foreign-function
in the following cases::name
keyword option in the foreign function definition:name
keyword option with a symbol in the foreign function definitionnil
or a function of two arguments, the Lisp symbol and the foreign language. The function can be invoked to compute a name for a foreign function that was not named when defined.
:name
keyword option, one of the following conversions takes place:*lisp-symbol-to-foreign-string-method*
is a function of two arguments, the function is called with the symbol and the language as arguments. If the function returns a string, that string is used as the symbol name.nil
, the default symbol name is translated into a form that the foreign language can understand. The Lisp symbol name is lowercased, dashes in the name are converted to underbar characters, and an underbar prefix or suffix is added if appropriate.;; To control the C foreign names of the Lisp functions #'test1, ;; #'test2, and #'test3, first check that there are no undefined ;; foreign symbols. > (foreign-undefined-symbol-names) NIL> (defun my-lisp-to-foreign-names (lisp-symbol language) (when (eq language :C) (cdr (assq lisp-symbol '((test1 . "my_test_1") (test2 . "my_test_2") (test3 . "my_test_3")))))) MY-LISP-TO-FOREIGN-NAMES
> (setq *lisp-symbol-to-foreign-string-method* #'MY-LISP-TO-FOREIGN-NAMES) #<Interpreted-Function (NAMED-LAMBDA MY-LISP-TO-FOREIGN-NAMES ...) 9CF51E>
> (def-foreign-function test2) TEST2
> (foreign-undefined-symbol-names) ("my_test_2")
> (def-foreign-function test47) TEST47
;; The function #'test2 used the new method, while #'test47 ;; did not. > (foreign-undefined-symbol-names) ("test47" "my_test_2")
;; Get rid of these "test" undefined foreign symbols. > (dolist (x (foreign-undefined-symbol-names)) (unintern-foreign-symbol x)) NIL
def-foreign-callable
, def-foreign-function
Function
load-foreign-files
files&optional
libraries
load-foreign-files
loads foreign language compiled (.o
) files into Lisp.
"-lc" "-lm" "-lucb"
); that is, the loader automatically searches the C, math run-time, and VCB compatibility libraries.
"-lc"
in the list.
"-lF77"
,"-lM77"
, and"-lV77"
along with the C libraries"-lc"
and"-lm"
.
"-lpc"
with the C libraries"-lc"
and"-lm"
.
def-foreign-function
.
;;; This example assumes that the file "string-test.c" contains ;;; code defining "string_function" and "test_string" and that it ;;; has been compiled using "cc -c string-test.c". ;; This single file can be loaded as follows: > (load-foreign-files "string-test.o") ;;; Loading foreign object file "string-test.o" T;; A single file can also be loaded by including the name in a ;; list. All loads involving more than one file must be done in ;; this way. > (load-foreign-files '("string-test.o")) ;;; Loading foreign object file "string-test.o" T
load-foreign-libraries
Function
load-foreign-libraries
strings&optional
libraries
load-foreign-libraries
loads functions from foreign language compiled library (.a
) files into Lisp.
"fn"
for C functions namedfn
, and"fn_"
for FORTRAN functions namedfn
. Such functions are then called from Lisp with the namefn
. Symbols that have been defined bydef-foreign-function
ordef-foreign-struct
since the last load are loaded automatically and should not be specified here. The strings argument is provided for backward compatibility withforeign-load-libraries
; it should normally benil
.
"-lc" "-lm"
); that is, the loader automatically searches the C and math run-time libraries. If you wish to search other libraries as well as the C run-time library, you must include"-lc"
in the list.
"-lF77"
,"-lM77"
, and"-lV77"
along with the C libraries"-lc"
and"-lm"
.
"-lpc"
with the C libraries"-lc"
and"-lm"
.
;; When loading foreign libraries for FORTRAN code, ;; use the following arguments: > (load-foreign-libraries nil '("-lV77" "-lF77" "-lM77" "-lm" "-lc")) T;; When loading foreign libraries for C code, ;; use the following arguments: > (load-foreign-libraries nil '("-lm" "-lc")) T
;; When loading foreign libraries for Pascal code, ;; use the following arguments: > (load-foreign-libraries nil '("-lpc" "-lm" "-lc")) T
load-foreign-files
Function
make-foreign-pointer &key :address :type :static :alignment
make-foreign-pointer
makes a foreign pointer object of the specified type that points at a specified address. If you do not specify an address, an appropriate amount of foreign storage is allocated to hold the object that is pointed at.
make-foreign-pointer
accepts the following keyword arguments; note that you must specify either the:address
or:type
keyword argument::address
:type
:static
nil
value, the foreign storage that is created is preserved in any image that you save by invoking the functiondisksave
; the value pointed to by the foreign pointer is not reinitialized when the saved image is started up. If the value of this keyword argument isnil
, foreign storage is not preserved when you save the image; this value is the default.
:alignment
M
and remainder R
, the foreign pointer object that is created points to foreign storage with a base address that is congruent toR
modulo the least common multiple ofM
and the:alignment
keyword argument. The default value of this argument is 1.
make-foreign-pointer
will not be reclaimed. If you want the space to be recovered later and do not needmake-foreign-pointer
's:address
and:static
functionality, usemalloc-foreign-pointer
.
> (setq example-pointer (make-foreign-pointer :type '(:pointer :signed-32bit))) #<Foreign-Pointer 7500CC (:POINTER :SIGNED-32BIT)>
foreign-value
, malloc-foreign-pointer
Function
malloc-foreign-pointer &key :type :alignment
malloc-foreign-pointer
makes a foreign pointer object of the specified type by using the library function"malloc"
; it returns foreign storage. The functionfree-foreign-pointer
frees any foreign storage returned by this function.
malloc-foreign-pointer
accepts the following keyword arguments::type
:alignment
M
and remainderR
, the foreign pointer object that is created points to foreign storage with a base address that is congruent toR
modulo the least common multiple ofM
and the:alignment
keyword argument. The default value of this argument is 1.
make-foreign-pointer
and specifying only the:type
keyword argument. Note that space used bymalloc-foreign-pointer
will be reclaimed. If you do not need the space to be recovered later and do needmake-foreign-pointer
's:address
and:static
functionality, usemake-foreign-pointer
.
disksave
.
;; Define a synonym type for an array of signed 16-bit integers. > (def-foreign-synonym-type array-example-type (:pointer (:array :signed-16bit (10)))) #<Foreign-Type (:POINTER (:ARRAY :SIGNED-16BIT (10))) 9BB196> ;; Malloc a foreign array, set its contents, and examine one ;; entry. > (setq example-array (malloc-foreign-pointer :type 'array-example-type))#<Foreign-Pointer 6F50C0 (:POINTER (:ARRAY :SIGNED-16BIT (10)))> > (dotimes (i 10) (setf (foreign-aref example-array i) i)) NIL
> (foreign-aref example-array 4) 4 ;; Now free the foreign storage occupied by the array. > (free-foreign-pointer example-array) NIL
;; Malloc two more foreign arrays; notice the address of example- ;; array-1 is the same as that of example-array (which was just ;; freed), while the address of example-array-2 is different. > (setq example-array-1 (malloc-foreign-pointer :type 'array- example-type)) #<Foreign-Pointer 6F50A0 (:POINTER (:ARRAY :SIGNED-16BIT (10)))>
> (setq example-array-2 (malloc-foreign-pointer :type 'array- example-type)) #<Foreign-Pointer 6F50C0 (:POINTER (:ARRAY :SIGNED-16BIT (10)))>
> (dotimes (i 10) (setf (foreign-aref example-array-1 i) (+ i 20))) NIL
> (dotimes (i 10) (setf (foreign-aref example-array-2 i) i)) NIL
> (foreign-aref example-array-1 4) 24
> (foreign-aref example-array-2 4) 4
> (foreign-aref example-array 4) 4
> (free-foreign-pointer example-array-1) NIL
> (free-foreign-pointer example-array-2) NIL
free-foreign-pointer
, make-foreign-pointer
Function
stationary-object-p
lisp-object
stationary-object-p
returns a non-nil
value if the specified Lisp object does not move during a garbage collection; otherwise, it returnsnil
.
Note:
All modifiable Lisp data that are passed to a foreign function must be stationary. Examples of stationary data include data that have been allocated within a call to the macrowith-static-area
or symbols that have been freshly created in a package by the Common Lisp functionintern
; note that the functionread
callsintern
. If dynamic data are passed to foreign functions, the results are unpredictable.
def-foreign-struct
or by invoking the functionmake-foreign-pointer
without specifying the:address
keyword argument, the foreign storage is always stationary and writable. Thus, you can always safely pass foreign pointers of type:arbitrary
or :pointer
to foreign functions.
;; Make two vectors, v and stationary-v; the first is not ;; stationary, while the second, created using the macro ;; with-static-area, is stationary. > (setq v (make-array 10)) #<Simple-Vector T 10 9DD086>undefine-foreign-type> (stationary-object-p v) NIL
> (setq stationary-v (with-static-area (make-array 10))) #<Simple-Vector T 10 8A0F7E>
> (stationary-object-p stationary-v) T
;; Since 'format is an interned symbol, it is stationary. ;; So is its symbol function. > (stationary-object-p 'format) T
> (stationary-object-p #'format) T
Function
undefine-foreign-type
foreign-type-name
undefine-foreign-type
removes the name of a foreign type from the internal list of defined types.
> (def-foreign-synonym-type renamed-signed-32bit :signed-32bit) #<Foreign-Type :SIGNED-32BIT 6E6D6E>> (undefine-foreign-type 'renamed-signed-32bit) RENAMED-SIGNED-32BIT
def-foreign-struct
, def-foreign-synonym-type
Function
unintern-foreign-symbol
symbol-name
unintern-foreign-symbol
makes a foreign symbol inaccessible for general use. You can reuse the name of the uninterned symbol in newly loaded foreign object code without changing previously loaded code.
"sym"
for C symbols namedsym
"sym_"
for FORTRAN symbols namedsym
def-foreign-function
with names of symbols that you have uninterned with this function.
;; This form uninterns all undefined foreign symbols. > (dolist (x (foreign-undefined-symbol-names)) (unintern-foreign-symbol x)) NIL
foreign-undefined-symbol-names
Function
writable-object-p
lisp-object
writable-object-p
returns a non-nil
value if the specified Lisp object can be written; otherwise, it returnsnil
.
;; Make two vectors, v and stationary-v; the first is not ;; stationary, while the second, created using the macro ;; with-static-area, is stationary. They are both writable. > (setq v (make-array 10)) #<Simple-Vector T 10 9DEF5E>> (stationary-object-p v) NIL
> (setq stationary-v (with-static-area (make-array 10))) #<Simple-Vector T 10 8A0FC6>
> (stationary-object-p stationary-v) T
> (writable-object-p stationary-v) T
> (writable-object-p v) T
;; Since 'format is an interned symbol, it is stationary. So is ;; its symbol function. The symbol 'format is writable (although ;; it is necessary to be VERY careful when writing on a Lisp ;; symbol from foreign code), but the symbol function for 'format ;; is not.
> (stationary-object-p 'format) T
> (stationary-object-p #'format) T
> (writable-object-p 'format) T
> (writable-object-p #'format) NIL
Generated with Harlequin WebMaker