Pointer Functions
A predicate for pointer values: returns #t for C pointer
objects as well as other values that can be used as pointers:
#f (used as a NULL pointer), byte strings (used as memory
blocks), and some additional internal objects (ffi-objs and
callbacks, see section 7). The result is
#f for other values.
(ptr-ref cptr ctype [['abs] offset]) PROCEDURE
(ptr-set! cptr ctype [['abs] offset] value) PROCEDURE
The pre-ref procedure return the object referenced by
cptr, using the given ctype. The ptr-set!
procedure stores the value in the memory cptr points to, using
the given ctype for the conversion, and returns void.
In each case, offset defaults to 0 (which is the only value
that should be used with ffi-obj objects, see
section 7). If an offset index is given, the
value is stored at that location, considering the pointer as a vector
of ctypes -- so the actual address is the pointer plus the size
of ctype multiplied by offset. In addition, a 'abs
flag can be used to use the offset as counting bytes rather then
increments of the specified ctype.
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:
> (define block (malloc _int 5))
> (ptr-set! block _int 0 196353)
> (map (lambda (i) (ptr-ref block _byte i)) '(0 1 2 3))
(1 255 2 0)
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.
(ptr-equal? cptr1 cptr2) PROCEDURE
Compares the values of the two pointers. (Note that two different Scheme pointer objects can contain the same pointer.)
(ptr-add cptr offset-k [ctype]) PROCEDURE
Returns a cpointer that is like cptr offset by offset-k
instances of ctype. If ctype is not provided, cptr
is offset by offset-k bytes.
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 safey 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.)
(set-ptr-offset! cptr offset-k [ctype]) PROCEDURE
Sets the offset component of an offset pointer. The arguments are used in the
same way as ptr-add. Raises an error if it is given a pointer that
has no offset.
(ptr-add! cptr offset-k [ctype]) PROCEDURE
Like ptr-add, but destructively modifies the offset contained in a
pointer. (This can also be done using ptr-offset and
set-ptr-offset!.)
Returns the Scheme object that is the tag of the given cptr pointer.
(set-cpointer-tag! cptr tag) PROCEDURE
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).
(memmove cptr [offset-k]
src-cptr [src-offset-k]
count-k [ctype])
Copies to cptr from src-cptr. The destination pointer can be
offset by an optional offset-k, which is in bytes if ctype
is not supplied, or in ctype instances when supplied.
The source pointer can be similarly offset by src-offset-k.
The number of bytes copied from source to destination is determined by count-k,
which is also in bytes if ctype is not supplied, or in ctype
instances when supplied.
(memcpy cptr [offset-k]
src-cptr [src-offset-k]
count-k [count-ctype])
Like memmove, but the result is
undefined if the destination and source overlap.
(memset cptr [offset-k]
byte
count-k [count-ctype])
Similar to memmove, but the destination is uniformly filled with
byte (i.e., an exact integer between 0 and 255 includive).
4.1 Memory Management
For general information on C-level memory management with MzScheme, see Inside PLT MzScheme.
(malloc bytes-or-type
[type-or-bytes]
[cptr]
[mode] ['fail-ok]) PROCEDURE
Allocates a memory block of a specified size using a specified allocation. The result is a
cpointer to the allocated memory. The four arguments can appear in
any order since they are all different types of Scheme objects; a
size specification is required at minimum:
If a C type
bytes-or-typeis given, its size is used to the block allocation size.If an integer
bytes-or-typeis given, it specifies the required size in bytes.If both
bytes-or-typeandtype-or-bytesare 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
cptrpointer is given, its contents is copied to the new block, it is expected to be able to do so.A symbol
modeargument can be given, which specifies what allocation function to use. It should be one of'nonatomic(uses scheme_malloc from MzScheme'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
'failokflag 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 any pointer-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 Scheme
pointer object, freeing the memory when the pointer object is
collected, but beware of aliasing).
(end-stubborn-change cpointer) PROCEDURE
Uses scheme_end_stubborn_change on the given stubborn-allocated pointer (see Inside PLT MzScheme).
(register-finalizer obj finalizer-proc) PROCEDURE
Registers a finalizer procedure finalizer-proc with the given obj
which can be any Scheme (GC-able) object. The finalizer is registered with a
will executor (see section 13.3 in PLT MzScheme: Language Manual); it is invoked when obj is
about to be collected. (This is done by a thread that is in charge of
triggering these will executors.)
This is 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 Scheme object -- even ones that have nothing to do with foreign code. Note, however, that the finalizer is registered for the Scheme 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:
(define _bytes/free (make-ctype _pointer #f ; a Scheme bytes can be used as a pointer (lambda (x) (let ([b (make-byte-string x)]) (register-finalizer x free) b))))
This 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:
(define _bytes/free
(make-ctype _pointer
#f ; a Scheme bytes can be used as a pointer
(lambda (x)
(let ([b (make-byte-string x)])
(register-finalizer b
(lambda (_)
(printf "Releasing ~s\n" b)
(free x)))
b))))
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 the _ to b
will solve this problem. (Removing the debugging message also avoids the problem,
since the finalization procedure would then not close over b.)
(make-sized-byte-string cptr length) PROCEDURE
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 Scheme 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 Scheme byte
string, because the offset pointer would be to the middle of a
collectable object (which is not allowed).