All Manuals > Foreign Language Interface User Guide and Reference Manual > 3 FLI Pointers

3.3 Pointer dereferencing and coercing

The dereference function returns the value stored at the location held by a pointer, provided the type of the object is an immediate type and not a structure or an aggregate type. For now, you can consider immediate data types to be the simple types such as :int, :byte, and :char, and aggregate types to consist of structures defined using :struct. Full details about types are given in 2 FLI Types, and the use of the dereference function with aggregate types is discussed further in 5 Advanced Uses of the FLI.

The dereference function supports the setf function which can therefore be used to set values at the address pointed to by the pointer. In the following example an integer is allocated and a pointer to the integer is returned. Then dereference and setf are used to set the value of the integer to 12. Finally, the value of the integer is returned using dereference.

(setq point5 (fli:allocate-foreign-object :type :int))
(setf (fli:dereference point5) 12)
(fli:dereference point5)

The function dereference has an optional :type keyword which can be used to return the value pointed to by a pointer as a different type. This is known as coercing a pointer. The default value for :type is the type the pointer is specified as pointing to. In the next example the value at point5 is returned as a Lisp boolean even thought it was set as an :int. Because the value at point5 is not 0, it is returned as t.

(fli:dereference point5 :type '(:boolean :int))

Recall that at the end of the previous section the function pointer-element-type was demonstrated. What follows is an example which uses this function to clarify the issue of pointers and types.

The first action consists of allocating an integer, and setting up a pointer to this integer:

(setq pointer-a (fli:allocate-foreign-object :type :int))

Now we use fli:copy-pointer to make a copy of pointer-a, but with the type of the new pointer changed to be a :byte. We call this pointer pointer-b.

(setq pointer-b (fli:copy-pointer pointer-a :type :byte))

We now have two pointers which point to the same memory location, but one thinks it is pointing to an :int, and the other thinks it is pointing to a :byte. Test this by using the following two commands:

(fli:pointer-element-type pointer-a)
(fli:pointer-element-type pointer-b)

Similar commands using pointer-element-size show that pointer-a is pointing to an element of size 4, and pointer-b to an element of size 1.

So far we have seen the use of the :type keyword to specify how to set up or dereference a pointer to obtain values in the format we want. There is, however, a further level of abstraction in pointer typing which uses the :pointer-type keyword instead of the :type keyword.

The following two commands produce identical pointers, but one uses the :type keyword, and the other uses the :pointer-type keyword:

(fli:make-pointer :address 0 :type :int)
(fli:make-pointer :address 0 :pointer-type '(:pointer :int))

In the instance above there is no advantage in using the :pointer-type option. However, :pointer-type can be very useful when used in combination with a defined type, as the next example shows.

Imagine you are writing a program with many statements creating pointers to a certain type, for example :byte, and this is done using the :type keyword. If half way through coding the type to be pointed to was changed to a :char, every individual statement would need to be changed. However, if a general pointer type had been defined at the start and all the statements had used the :pointer-type keyword to refer to that particular type, only one statement would need to be changed: the initial definition of the pointer type. The following code illustrates this:

(fli:define-c-typedef my-pointer-type (:pointer :byte))
(fli:make-pointer :address 0 :pointer-type 'my-pointer-type)
...
(fli:make-pointer :address 100 :pointer-type 'my-pointer-type)

The above code consists of a definition of a new pointer type, called my-pointer-type, which points to a :byte. Following it are one hundred lines of code using my-pointer-type. If you decide that all the pointers made should actually point to a :char, only the first line needs to be changed, as shown below:

(fli:define-c-typedef my-point-type (:pointer :char))

The program can now be re-compiled. The use of :pointer-type with pointers is thus analogous to the use of constants instead of absolute numbers in programming.

The function pointer-pointer-type returns the pointer type of a foreign pointer.


Foreign Language Interface User Guide and Reference Manual - 01 Dec 2021 19:34:57