On this page:
ptr_  t?
ptr_  t/  gcable?
void_  t*?
void_  t*/  gcable?
ffi2-malloc
ffi2-free
ffi2-ref
ffi2-set!
ffi2-cast
ffi2-add
ffi2-memcpy
ffi2-memmove
ffi2-memset
ffi2-malloc-manual-box
ffi2-free-manual-box
ffi2-manual-box-ref
ffi2-manual-box-set!
ptr_  t->uintptr_  t
uintptr_  t->ptr_  t
9.2.0.3

2.5 Foreign Pointers🔗ℹ

A pointer object encapsulates a memory address and a potentially empty sequence of symbolic tags. A pointer object may refer to an address that under the control of Racket’s memory manager and garbage collection, or it may refer to an address is managed externally.

The base type for pointers is ptr_t (aliased as void_t*), and new pointer types can be created via define-ffi2-type with either an existing pointer type, a struct_t type, a union_t type, or an a array_t type.

A pointer’s tags enable sanity checking that the right kind of pointer is provided to an operation. If an operation expects a pointer with a certain sequence of tags, it accepts a pointer with additional tags added to the end, so additional tags form a pointer subtype. A ptr_t representation has no tags, which means that a C conversion to Racket via ptr_t is not accepted by any context that expects some tag, whereas a pointer with any tags is accepted as a ptr_t representation to translate to C. Whether a pointer object represents an address managed by Racket’s garbage collector is independent of its tags.

procedure

(ptr_t? v)  boolean?

  v : any/c

procedure

(ptr_t/gcable? v)  boolean?

  v : any/c

procedure

(void_t*? v)  boolean?

  v : any/c

procedure

(void_t*/gcable? v)  boolean?

  v : any/c
The ptr_t? or void_t*? predicate recognizes any pointer object, while ptr_t/gcable? or void_t*/gcable? recognizes a pointer object that represents a reference to memory that is managed by Racket’s garbage collector.

syntax

(ffi2-malloc maybe-mode
             maybe-type
             n-expr maybe-bytes
             maybe-as-type)
 
maybe-mode = 
  | #:gcable
  | #:gcable-traced
  | #:gcable-immobile
  | #:gcable-traced-immobile
  | #:manual
     
maybe-type = 
  | type
     
maybe-bytes = 
  | #:bytes
     
maybe-as-type = 
  | #:as as-type
Allocates memory.

The amount of allocated memory depends on n-expr. If no type is provided as maybe-type, or if maybe-bytes is #:bytes, then the allocated memory spans as many bytes as the value of n-expr. Otherwise, the allocated memory’s size is the result of (* n-expr (ffi2-sizeof maybe-type)).

If maybe-as is specified, then the result is cast to as-type in the sense of ffi2-cast. Otherwise, the result is a pointer object encapsulating the address of allocated memory. If maybe-type is a struct_t, union_t, or size array_t type (and maybe-as is not specified), the result is a pointer object using the representation of maybe-type. Otherwise, the result is a pointer object using the representation of void_t*.

By default, allocation uses #:gcable mode, but a maybe-mode specification can pick any of the supported modes:

  • #:gcable: Allocates uninitialized memory in Racket’s garbage-collected space, i.e., GCable memory. The allocated memory becomes eligible for garbage collection when it is not referenced by any reachable pointer object or traced allocated memory. Even before collection, the memory manager may relocate the object, but garbage collection or relocation cannot happen with a foreign-procedure call is active.

  • #:gcable-immobile: Like #:gcable, but the allocated memory will not be relocated by a different address by the memory manager as long as it is not collected.

  • #:gcable-traced: Like #:gcable, but the allocated memory is traced, meaning that it can itself contain references to other memory that is allocated using #:gcable variants. In particular, references from traced memory are updated by the memory manager if it moves the referenced objects. Traced memory can also contain references to non-GCable memory, but beware of the possibility that Racket’s garbage collector takes over an an address range that was formerly under external control but deallocated.

  • #:gcable-traced-immobile: Like #:gcable-traced, but the allocated memory will not be relocated by a different address by the memory manager as long as it is not collected (but it can contain references to mobile objects).

  • #:manual: Allocates outside of Racket’s garbage-collected space. The allocated memory is never relocated by the garbage collection, and it must be freed explicitly with ffi2-free.

procedure

(ffi2-free ptr)  void?

  ptr : void_t*?
Deallocates memory that was allocated with ffi2-malloc in #:manual mode.

syntax

(ffi2-ref ptr-expr type maybe-offset)

 
maybe-offset = 
  | offset-expr
  | offset-expr #:bytes
Extracts a value from the address referenced by ptr-expr plus (potentially) maybe-offset. The extracted value in memory uses the C representation of type, and the result is the value converted to the Racket representation of type. No tags of the result of ptr-expr are checked; it assumed to be a valid pointer to a type representation.

If offset-expr is followed by #:bytes, it the result of offset-expr is used as an offset to add to the address represented by the result of ptr-expr. If #:bytes is not present, that offset is multiplied by (ffi2-sizeof type).

syntax

(ffi2-set! ptr-expr type maybe-offset val-expr)

 
maybe-offset = (code:bank)
  | offset-expr
  | offset-expr #:bytes
Install a value at the address referenced by ptr-expr plus (potentially) maybe-offset. The installed value in memory uses the C representation of type, and it is converted from the result of val-expr as the Racket representation for type. No tags of the result of ptr-expr are checked; it assumed to be a valid destination for a type representation.

When maybe-offset is not empty, it specifies an address offset in the same way as for ffi2-ref.

syntax

(ffi2-cast expr option ...)

 
option = #:from from-type
  | #:to to-type
  | #:offset maybe-type n-expr
     
maybe-type = 
  | type
Converts the Racket representation produced by expr from one foreign type’s representation to another. If from-type or to-type is not specified, each defaults to ptr_t. Both from-type and to-type must be pointer types, or they must both be scalar types.

If the #:offset option is provided, the resulting pointer is shifted to represent an address that is n bytes later, where n is the result of n-expr multiplied by (ffi2-sizeof maybe-type) or by 1 if maybe-type is empty. An #:offset option cannot be provided for casting between scalar types.

syntax

(ffi2-add ptr-expr n-expr)

(ffi2-add ptr-expr type n-expr)
A shorthand for (ffi2-cast ptr-expr #:offset n-expr) or (ffi2-cast ptr-expr #:offset type n-expr #:to (array_t type *)).

procedure

(ffi2-memcpy dest    
  src    
  len    
  [#:dest-offset dest-offset    
  #:src-offset src-offset])  void?
  dest : ptr_t?
  src : ptr_t?
  len : exact-nonnegative-integer?
  dest-offset : exact-integer? = 0
  src-offset : exact-integer? = 0

procedure

(ffi2-memmove dest    
  src    
  len    
  [#:dest-offset dest-offset    
  #:src-offset src-offset])  void?
  dest : ptr_t?
  src : ptr_t?
  len : exact-nonnegative-integer?
  dest-offset : exact-integer? = 0
  src-offset : exact-integer? = 0

procedure

(ffi2-memset dest    
  byte    
  len    
  [#:dest-offset dest-offset])  void?
  dest : ptr_t?
  byte : byte_t?
  len : exact-nonnegative-integer?
  dest-offset : exact-integer? = 0
The ffi2-memcpy and ffi2-memmove functions copy len bytes from the address represented by (ffi2-add src src-offset) to the address represented by (ffi2-add dest dest-offset). In the case of ffi2-memcpy, the source and destination regions must not overlap.

The ffi2-memcpy function sets len bytes at the address represented by (ffi2-add dest dest-offset) so that each byte’s value is byte.

procedure

(ffi2-malloc-manual-box v)  ptr_t?

  v : any/c

procedure

(ffi2-free-manual-box p)  void?

  p : ptr_t?

procedure

(ffi2-manual-box-ref p)  any/c

  p : ptr_t?

procedure

(ffi2-manual-box-set! p v)  void

  p : ptr_t?
  v : any/c
The ffi2-malloc-manual-box function allocates an initializes a manual box, which is manually allocated memory that holds a single Racket value. The box must be explicitly freed with ffi2-free-manual-box. The value in the box can be accessed with ffi2-manual-box-ref or changed with ffi2-manual-box-set!.

procedure

(ptr_t->uintptr_t ptr)  exact-nonnegative-integer?

  ptr : ptr_t?

procedure

(uintptr_t->ptr_t int)  ptr_t?

  int : exact-nonnegative-integer?
Conversions between addresses represented as pointers and addresses as represented as integers.

Beware that the integer form of an address managed by Racket’s garbage collector can become immediately invalid, unless an object at the address was allocated as immobile.