4 Pointer Functions
Returns
#t if
v is a C pointer or a value that can
be used as a pointer:
#f (used as a
NULL pointer), byte
strings (used as memory blocks), or some additional internal objects
(
ffi-objs and callbacks, see
Unexported Primitive Functions).
Returns
#f for other values.
Compares the values of the two pointers. Two different Racket
pointer objects can contain the same pointer.
If the values are both C pointers—as opposed to #f, a byte
string, ffi-obj, or callback—this comparison is the same as
equal?.
Returns a cpointer that is like cptr offset by
offset instances of ctype.
The resulting cpointer keeps the base pointer and offset separate. The
two pieces are combined at the last minute before any operation on the
pointer, such as supplying the pointer to a foreign function. In
particular, the pointer and offset are not combined until after all
allocation leading up to a foreign-function call; if the called
function does not itself call anything that can trigger a garbage
collection, it can safely use pointers that are offset into the middle
of a GCable object.
A predicate for cpointers that have an offset, such as pointers that
were created using
ptr-add. Returns
#t even if such
an offset happens to be 0. Returns
#f for other cpointers
and non-cpointers.
Returns the offset of a pointer that has an offset. The resulting
offset is always in bytes.
4.1 Pointer Dereferencing
Sets the offset component of an offset pointer. The arguments are
used in the same way as
ptr-add. If
cptr has no
offset, the
exn:fail:contract exception is raised.
The
ptr-ref procedure returns the object referenced by
cptr, using the given
type. The
ptr-set!
procedure stores the
val in the memory
cptr points
to, using the given
type for the conversion.
In each case, offset defaults to 0 (which is the
only value that should be used with ffi-obj objects, see
Unexported Primitive Functions). If an offset index is
non-0, the value is read or stored at that location,
considering the pointer as a vector of types — so the
actual address is the pointer plus the size of type
multiplied by offset. In addition, a 'abs flag can
be used to use the offset as counting bytes rather then
increments of the specified type.
Beware that the ptr-ref and ptr-set! procedure do
not keep any meta-information on how pointers are used. It is the
programmer’s responsibility to use this facility only when
appropriate. For example, on a little-endian machine:
In addition, ptr-ref and ptr-set! cannot detect when
offsets are beyond an object’s memory bounds; out-of-bounds access can
easily lead to a segmentation fault or memory corruption.
Copies to cptr from src-cptr. The destination
pointer can be offset by an optional offset, which is in
type instances. The source pointer can be similarly offset
by src-offset. The number of bytes copied from source to
destination is determined by count, which is in type
instances when supplied.
Like
memmove, but the result is undefined if the destination
and source overlap.
Similar to
memmove, but the destination is uniformly filled
with
byte (i.e., an exact integer between 0 and 255
inclusive). When a
type argument is present, the result
is that of a call to memset with no
type argument and the
count multiplied by the size associated with the
type.
Returns the Racket object that is the tag of the given cptr
pointer.
Sets the tag of the given
cptr. The
tag argument can
be any arbitrary value; other pointer operations ignore it. When a
cpointer value is printed, its tag is shown if it is a symbol, a byte
string, a string. In addition, if the tag is a pair holding one of
these in its
car, the
car is shown (so that the tag
can contain other information).
4.2 Memory Management
For general information on C-level memory management with Racket,
see Inside: Racket C API.
Allocates a memory block of a specified size using a specified
allocation. The result is a cpointer to the allocated
memory. Although not reflected above, the four arguments can appear in
any order since they are all different types of Racket objects; a size
specification is required at minimum:
If a C type bytes-or-type is given, its size is used
to the block allocation size.
If an integer bytes-or-type is given, it specifies the
required size in bytes.
If both bytes-or-type and type-or-bytes are given,
then the allocated size is for a vector of values (the multiplication of
the size of the C type and the integer).
If a cptr pointer is given, its content is copied to
the new block.
A symbol mode argument can be given, which specifies
what allocation function to use. It should be one of
'nonatomic (uses scheme_malloc from
Racket’s C API), 'atomic
(scheme_malloc_atomic), 'stubborn
(scheme_malloc_stubborn), 'uncollectable
(scheme_malloc_uncollectable), 'eternal
(scheme_malloc_eternal), 'interior
(scheme_malloc_allow_interior),
'atomic-interior
(scheme_malloc_atomic_allow_interior), or
'raw (uses the operating system’s malloc,
creating a GC-invisible block).
If an additional
'failok flag is given, then
scheme_malloc_fail_ok is used to wrap the call.
If no mode is specified, then 'nonatomic allocation is used
when the type is a _gcpointer- or _scheme-based
type, and 'atomic allocation is used otherwise.
Uses the operating system’s free function for
'raw-allocated pointers, and for pointers that a foreign
library allocated and we should free. Note that this is useful as
part of a finalizer (see below) procedure hook (e.g., on the Racket
pointer object, freeing the memory when the pointer object is
collected, but beware of aliasing).
Allocates memory large enough to hold one arbitrary (collectable)
Racket value, but that is not itself collectable or moved by the
memory manager. The cell is initialized with
v; use the type
_scheme with
ptr-ref and
ptr-set! to get
or set the cell’s value. The cell must be explicitly freed with
free-immobile-cell.
Registers a finalizer procedure
finalizer-proc with the given
obj, which can be any Racket (GC-able) object. The finalizer
is registered with a will executor; see
make-will-executor. The finalizer is invoked when
obj is about to be collected. (This is done by a thread that
is in charge of triggering these will executors.)
Finalizers are mostly intended to be used with cpointer objects (for
freeing unused memory that is not under GC control), but it can be
used with any Racket object—even ones that have nothing to do with
foreign code. Note, however, that the finalizer is registered for the
Racket object. If you intend to free a pointer object, then
you must be careful to not register finalizers for two cpointers that
point to the same address. Also, be careful to not make the finalizer
a closure that holds on to the object.
For example, suppose that you’re dealing with a foreign function that returns a
C string that you should free. Here is an attempt at creating a suitable type:
The above code is wrong: the finalizer is registered for x,
which is no longer needed once the byte string is created. Changing
this to register the finalizer for b correct this problem,
but then free will be invoked on it instead of on x.
In an attempt to fix this, we will be careful and print out a message
for debugging:
but we never see any printout. The problem is that the finalizer is a
closure that keeps a reference to b. To fix this, you should
use the input argument to the finalizer. Simply changing
ignored to b will solve this problem. (Removing the
debugging message also avoids the problem, since the finalization
procedure would then not close over b.)
Returns a byte string made of the given pointer and the given length.
No copying is done. This can be used as an alternative to make
pointer values accessible in Racket when the size is known.
If cptr is an offset pointer created by ptr-add, the
offset is immediately added to the pointer. Thus, this function cannot
be used with ptr-add to create a substring of a Racket byte
string, because the offset pointer would be to the middle of a
collectable object (which is not allowed).