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.
BOOL GetCursorPos( LPPOINT )
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,
LONG, which are used to associate a Lisp boolean value (
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
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 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
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.
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))
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