4.1 The Foreign Function Interface

4.1.8 Reference pages

copy-foreign-pointer Function

Syntax:copy-foreign-pointer foreign-pointer&key :static :malloc :alignment

The functioncopy-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.

The keyword arguments control how the foreign storage is allocated:

In this case, the values of both the: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

See Also: make-foreign-pointer,

def-foreign-callable Macro

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)

The macrodef-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.

The simplest form of the name-and-options argument todef-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.

The name-and-options argument can also be a list that consists of a symbol followed by keyword options. The following keyword options are available:

This keyword option specifies the default calling convention that the foreign function uses to call Lisp. The calling convention determines how arguments are passed to and received by the foreign function.

The language argument must be: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.

This keyword option specifies the name of the foreign function that calls the Lisp function. The foreign-name argument must be a string. The default value for this option is the print name of the symbol specified as the function-name component of the name-and-options argument todef-foreign-callable.

If you do not specify this option, one of the following conversions takes place:

This keyword option specifies that the value returned from Lisp to the foreign function must be coerced to the type given in the foreign-type argument. See Section 4.1.7 on page 105 for the possible foreign types and the Lisp types that are associated with them.

The arg-description argument determines the lambda list for the Lisp function that is being defined; it also determines the way in which the foreign arguments are converted to Lisp arguments. The syntax for this argument is described as follows:

This argument is the name that appears in the argument list of the resulting Lisp function.

This argument is a predefined type from Section 4.4, which also shows the valid call disciplines for foreign types.

Note: Foreign data passed to Lisp functions are copied into Lisp data types. Changes made to the Lisp data are not reflected in the associated foreign data.

You can supply declaration arguments by using the Common Lisp special formdeclare.

You can attach a documentation string to the name of the function with the optional documentation argument. The documentation type for this string isfunction.

For foreign callable Lisp functions to be properly linked with the foreign functions that call them, the macrodef-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 *)

See Also: def-foreign-callable

def-foreign-function Macro

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)

The macrodef-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.

Interpreted calls todef-foreign-function create interpreted Lisp functions, and compiled calls create compiled Lisp functions.

The simplest form of the name-and-options argument todef-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.

The name-and-options argument can also be a list that consists of a symbol followed by keyword options. The following keyword options are available:

This keyword option specifies the default calling convention for the foreign function. The calling convention determines how arguments are passed to the foreign function and the proper form for calling the function. The language argument must be either: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.

This keyword option specifies the name of the foreign function to be called. The foreign-name argument is a string or a symbol.

If you specify a symbol, one of the following conversions takes place:

  • If the value of the variable*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.

  • Otherwise, the symbol is translated into a form that the foreign language can understand. The Lisp symbol name is lowercased, any dashes in the name are converted to underbar characters, and an underbar prefix or suffix is added if appropriate.

If you do not specify this option, the conversions are similar to those specified for a symbol, except that the print name of the symbol specified as the function-name component of the name-and-options argument todef-foreign-function is used.

This keyword option specifies that the value returned by the foreign function is of the type given in the foreign-type argument. See Section 4.1.7 on page 105 for the possible foreign types and the Lisp types that are associated with them.

This keyword option specifies the maximum number of&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.

You can attach a documentation string to the name of the function with the optional documentation argument. The documentation type for this string isfunction.

The arg-description argument determines the lambda list for the Lisp function that is being defined; it also determines the way in which the Lisp arguments are converted to machine-level arguments. The syntax for this argument is described as follows:

This argument is the name that appears in the argument list of the resulting Lisp function. The arg-name argument can be a list of the appropriate form for a lambda list if there are any of the lambda list keywords&optional,&rest, or&key. You can list this argument with a default-value if you supply the optional argument foreign-type.

This argument specifies a predefined data type from Section 4.4. The default value is the special foreign type:arbitrary, which indicates that the coercion is based on the specified:language option.

Note: Not all changes made to foreign types that are passed by reference are reflected in the Lisp function that made the call. Only changes made to the foreign types:array,:string,:simple-string, and:simple-vector-type change the argument passed by the Lisp function.

When a linked FORTRAN program is run, the standard FORTRAN input/output (I/O) units are initialized with a call to the C functionf_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

All modifiable Lisp data that are passed to a foreign function must be stationary; that is, they must not move during a garbage collection. Examples of stationary data include data that have been allocated by a call to the macro 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

See Also: def-foreign-callable, load-foreign-files, stationary-object-p;with-static-area (in The User's Guide)

def-foreign-struct Macro

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

The macrodef-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.

In the simplest case, the name-and-options argument ofdef-foreign-struct is a symbol that names the foreign structure. The following functions are automatically defined to operate on instances of the foreign structure:

Alternatively, the name-and-options argument is a list that consists of a symbol followed by a list containing the: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:

Use the alignment-info argument list to guarantee that foreign storage associated with the foreign type being defined is constructed to start at a machine address that is congruent to the:remainder argument modulo the:modulus argument.

You can use the: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.

The following requirements must be met when you specify the:overlays and:offset options:

The: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.

The: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).

The: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.

Section 4.3 provides more information on the predefined types for foreign structures.

> (def-foreign-struct (example-struct 
                     (:alignment (:modulus 4 :remainder 2)))
    (slot-a :type :unsigned-32bit)
    (slot-b :type :signed-16bit))
EXAMPLE-STRUCT

See Also: 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 Macro

Syntax:def-foreign-synonym-type atomic-type-name previously-defined-type-name

The macrodef-foreign-synonym-type creates a synonym type for a previously defined type; that is, it associates a new name with an existing type.

The atomic-type-name argument is a symbol that names the synonym type. The previously-defined-type-name argument is the name of any predefined type found in Section 4.3 or any type derived from a predefined type.

The synonym type does not change if the foreign type named by the previously-defined-type-name argument is redefined. Thus, you can use a synonym name to preserve any foreign type information for the previously defined type before you redefine or undefine it.

;;; 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>

See Also: undefine-foreign-type

defined-foreign-type-p Function

Syntax:defined-foreign-type-p type-name

The functiondefined-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-TYPE

> (defined-foreign-type-p 'test-type) T

foreign-aref Function

typed-foreign-aref Function

Syntax:foreign-aref foreign-vector&rest indices

Syntax:typed-foreign-aref foreign-type foreign-vector&rest indices

The functionsforeign-aref andtyped-foreign-aref provide Lisp access to arrays that are defined in other languages.

Both functions check whether the specified array indices are defined for
the foreign array pointed at by the foreign-vector argument. The functions return the evaluated form of the array element specified by the indices. The functiontyped-foreign-aref also checks that the foreign array is of the specified type.

Note thattyped-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.

The foreign-vector argument is a foreign pointer that points to an object whose foreign type is: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.

The indices arguments specify which element of the array to return; in Common Lisp, the elements of a multidimensional array are stored in row-major order. The number of indices must correspond to the rank of the array, and each index must be in bounds for its dimension.

The foreign-type argument fortyped-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.

You can use the Common Lisp macrosetf 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>

> (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

foreign-pointer-address Function

foreign-pointer-p Function

foreign-pointer-type Function

foreign-typep Function

foreign-type-modulus Function

foreign-type-remainder Function

foreign-type-size Function

Syntax:foreign-pointer-address foreign-pointer

Syntax:foreign-pointer-p foreign-pointer

Syntax:foreign-pointer-type foreign-pointer

Syntax:foreign-typep foreign-pointer foreign-type

Syntax:foreign-type-modulus foreign-type

Syntax:foreign-type-remainder foreign-type

Syntax:foreign-type-size foreign-type

The functionsforeign-pointer-address,foreign-pointer-p,foreign-pointer-type, andforeign-typep return information about the specified foreign pointer.

The functionsforeign-type-modulus,foreign-type-remainder, andforeign-type-size return information about the specified foreign type.

The foreign-pointer argument must be a Lisp object of type:pointer.

The foreign-type argument is a symbol that names a valid foreign type. The foreign type can be one of the types listed in Section 4.3, or any type derived from a predefined type.

The functionforeign-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.

The functionforeign-pointer-p is true if its foreign-pointer argument is of type :pointer; otherwise, it is false.

The functionforeign-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.

The functionforeign-typep is true if the foreign-pointer argument is of the specified type; otherwise, it is false.

The functionforeign-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.

The functionforeign-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

See Also: def-foreign-struct

foreign-size-of Function

Syntax:foreign-size-of foreign-pointer-or-type

The functionforeign-size-of returns an integer value whose meaning depends on the specified argument:

The foreign-pointer-or-type argument specifies a foreign pointer object or the name of a previously defined foreign type. If a type is specified, it must be one of the predefined types listed in Section 4.3or any type derived from a foreign type.

If the size of the specified argument is undefined, an error is signaled.

For example, assume thatmy-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.

Note, however, that the value returned when this function is called with the argument(: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.

See Also: foreign-type-size

foreign-string-value Function

Syntax:foreign-string-value foreign-pointer

The functionforeign-string-value returns a copy of the string pointed at by the specified foreign pointer.

The foreign-pointer argument must be of type:pointer and must point to a character object or an array of character objects.

You can use the Common Lisp macrosetf 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 );
;;; }

;; 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 Function

Syntax:foreign-undefined-symbol-names

The functionforeign-undefined-symbol-names returns a list of the names of foreign symbols that are not currently associated with any foreign code or data.

The names are returned as Lisp strings.

;; 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

See Also: unintern-foreign-symbol

foreign-value Function

Syntax:foreign-value foreign-pointer

The functionforeign-value evaluates its foreign-pointer argument as follows:

You can use the Common Lisp macrosetf 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

See Also: make-foreign-pointer, malloc-foreign-pointer

foreign-variable-p Function

foreign-variable-address Function

foreign-variable-pointer Function

Syntax:foreign-variable-p string

Syntax:foreign-variable-address string

Syntax:foreign-variable-pointer string

The functionsforeign-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.

The string argument is a Lisp string that names the foreign variable as it appears in a foreign object file as follows:

When you save a Lisp image on disk with the functiondisksave, 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

See Also: foreign-undefined-symbol-names

free-foreign-pointer Function

Syntax:free-foreign-pointer foreign-pointer

The functionfree-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.

This function does not change the foreign pointer; however, the foreign storage pointed at can be reused by"malloc" at any time.

The foreign-pointer argument must be a Lisp object of type:pointer.

See Also: malloc-foreign-pointer

lisp-symbol-to-foreign-string-method* Variable

Syntax:*lisp-symbol-to-foreign-string-method*

The variable*lisp-symbol-to-foreign-string-method* is used by the macrosdef-foreign-callable anddef-foreign-function in the following cases:

The value of this variable must benil 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.

If you specify a symbol for the:name keyword option, one of the following conversions takes place:

;; 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

See also: def-foreign-callable, def-foreign-function

load-foreign-files Function

Syntax:load-foreign-files files&optional libraries

The functionload-foreign-files loads foreign language compiled (.o) files into Lisp.

The files argument is a list of strings that names the files to be loaded.

The default value for the libraries argument is the list ("-lc" "-lm" "-lucb" ); that is, the loader automatically searches the C, math run-time, and VCB compatibility libraries.

If you wish to search other libraries as well as the C run-time library, you must include"-lc" in the list.

If you load FORTRAN code, you should include the FORTRAN libraries"-lF77","-lM77", and"-lV77" along with the C libraries"-lc" and"-lm".

If you load Pascal code, you should include the Pascal library"-lpc" with the C libraries"-lc" and"-lm".

When you invoke this function, it loads all of the named files in the files argument; it then searches the list of libraries specified in the optional libraries argument and loads modules that contain any foreign symbols that have not yet been defined. These modules can include foreign symbols that were created by the function 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

See Also: load-foreign-libraries

load-foreign-libraries Function

Syntax:load-foreign-libraries strings&optional libraries

The functionload-foreign-libraries loads functions from foreign language compiled library (.a) files into Lisp.

The strings argument is a list of Lisp strings that name the foreign functions as they appear in a foreign object file:"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.

The default value for the libraries argument is the list ("-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.

If you load FORTRAN code, you should include the FORTRAN libraries"-lF77","-lM77", and"-lV77" along with the C libraries"-lc" and"-lm".

If you load Pascal code, you should include the Pascal library"-lpc" with the C libraries"-lc" and"-lm".

The foreign loader scans the libraries in the order they are given as arguments; it does this repeatedly until the set of undefined foreign symbols at the end of a pass is a subset of the undefined foreign symbols at the beginning of the pass.

;; 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

See Also: load-foreign-files

make-foreign-pointer Function

Syntax:make-foreign-pointer &key :address :type :static :alignment

The functionmake-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.

The functionmake-foreign-pointer accepts the following keyword arguments; note that you must specify either the:address or:type keyword argument:

This keyword argument is an integer address at which the foreign pointer points. If you do not specify this argument, foreign storage of the appropriate size for the specified type is used.

This keyword argument is the name of 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. If you know the type of the object being pointed at, you should specify this argument to allow the Compiler to execute type-checking code.

If this keyword argument has a non-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.

If the specified type or address has modulusM 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.

Note that space used bymake-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)>

See Also: foreign-value, malloc-foreign-pointer

malloc-foreign-pointer Function

Syntax:malloc-foreign-pointer &key :type :alignment

The function 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.

The functionmalloc-foreign-pointer accepts the following keyword arguments:

This keyword argument specifies the name of 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.

You must specify this keyword argument.

If the specified type has modulusM 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.

Invoking this function is similar to invokingmake-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.

The foreign storage is not preserved when you save the image by invoking the functiondisksave.

;; 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

See Also: free-foreign-pointer, make-foreign-pointer

stationary-object-p Function

Syntax:stationary-object-p lisp-object

The function stationary-object-p returns a non-nil value if the specified Lisp object does not move during a garbage collection; otherwise, it returnsnil.

The lisp-object argument can be any Lisp object.

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.

If you acquire foreign storage by using the constructor function defined withdef-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>

> (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

undefine-foreign-type Function

Syntax:undefine-foreign-type foreign-type-name

The functionundefine-foreign-type removes the name of a foreign type from the internal list of defined types.

The foreign-type-name argument is a symbol that names any previously defined foreign type. The symbol can name one of the predefined types listed in Section 4.3, any type derived from a predefined type, or a synonym type.

Use this function for removing types when you are redefining recursively defined foreign types.

> (def-foreign-synonym-type renamed-signed-32bit :signed-32bit)
#<Foreign-Type :SIGNED-32BIT 6E6D6E>

> (undefine-foreign-type 'renamed-signed-32bit) RENAMED-SIGNED-32BIT

See Also: def-foreign-struct, def-foreign-synonym-type

unintern-foreign-symbol Function

Syntax:unintern-foreign-symbol symbol-name

The functionunintern-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.

The symbol-name argument is a Lisp string that names the foreign symbol as it appears in a foreign object file as follows:

If you have loaded a file into a Lisp image, you can edit, recompile, and reload a new version of the file into the same image. You can then successfully invokedef-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

See Also: foreign-undefined-symbol-names

writable-object-p Function

Syntax:writable-object-p lisp-object

The functionwritable-object-p returns a non-nil value if the specified Lisp object can be written; otherwise, it returnsnil.

The lisp-object argument can be any Lisp object.

An example of a Lisp object that cannot be written is one that lies in a UNIX text address space.

;; 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


The Advanced User's Guide - 9 SEP 1996

Generated with Harlequin WebMaker