Note: The rest of the examples in this chapter only work in LispWorks for Windows.
The following example shows how to use the FLI to call a C function in a Win32 library. The function we are going to call returns the screen position of the mouse pointer, or cursor. The example consists of three stages: setting up the correct data types to pass and receive the data, defining and calling a FLI function to call the Win32 function, and collecting the values returned by the Win32 function to find where the cursor is.
The example uses the FLI to find the position of the cursor using the Windows function GetCursorPos
, which has the following C prototype:
BOOL GetCursorPos( LPPOINT )
The LPPOINT
argument is a pointer to the POINT
structure, which has the following C definition:
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT;
First we use the define-c-typedef macro to define a number of basic types which are needed to pass data to and from the Windows function.
(fli:define-c-typedef bool (:boolean :int))
(fli:define-c-typedef long :long)
This defines two types, BOOL
and LONG
, which are used to associate a Lisp boolean value (t
or nil
) with a C boolean of type int
, and a Lisp bignum
with a C long
. These are required because the Windows function GetCursorPos
returns a boolean to indicate if it has executed successfully, and the cursor's x and y positions are specified in a long
format in the POINT
structure.
Next, we need to define a structure for the FLI which is used to get the coordinates of the cursor. These coordinates will consist of an x and a y position. We use the define-c-typedef macro for this, and the resulting Lisp FLI code has obvious parallels with the C tagPOINT
structure.
(fli:define-c-struct tagpoint
(x long)
(y long))
The tagPOINT
structure for the FLI, corresponding to the C structure of the same name, has been defined. This now needs to be further defined as a type for the FLI, using define-c-typedef.
(fli:define-c-typedef point (:struct tagpoint))
Finally, a pointer type to point to the structure is required. It is this FLI pointer which will be passed to the Windows function GetCursorPos
, so that GetCursorPos
can change the x
and y
values of the structure pointed to.
(fli:define-c-typedef lppoint (:pointer point))
All the required FLI types have now been defined. Although it may seem that there is a level of duplicity in the definitions of the structures, pointers and types in this section, this was necessary to match the data structures of the C functions to which the FLI will interface. We can now move on to the definition of FLI functions to perform the interfacing.
This next step uses the define-foreign-function macro to define a FLI function, or interface function, to be used to call the GetCursorPos
function. An interface function takes its arguments, converts them into a C format, calls the foreign function, receives the return values, and converts them into a suitable Lisp format.
(fli:define-foreign-function (get-cursor-position "GetCursorPos")
((lp-point lppoint))
:result-type bool)
In this example, the defined FLI function is get-cursor-position
. It takes as its argument a pointer of type lppoint
, converts this to a C format, and calls GetCursorPos
. It takes the return value it receives from GetCursorPos
and converts it into the FLI bool
type we defined earlier.
We have now defined all the types and functions required to get the cursor position. The next step is to allocate memory for an instance of the tagPOINT
structure using allocate-foreign-object. The following line of code binds location
to a pointer that points to such an instance.
(setq location (fli:allocate-foreign-object :type 'point))
Finally, we can use our interface function get-cursor-position
to get the cursor position:
(get-cursor-position location)
The position of the cursor is now stored in a POINT
structure in memory, and location
is a pointer to that location. To find out what values are stored we use the foreign-slot-value accessor, which returns the value stored in the specified field of the structure.
(fli:foreign-slot-value location 'x)
(fli:foreign-slot-value location 'y)
LispWorks Foreign Language Interface User Guide and Reference Manual - 29 Sep 2017