On this page:
_ cpointer
_ cpointer/ null
define-cpointer-type
cpointer-has-tag?
cpointer-push-tag!

5.3 Tagged C Pointer Types

The unsafe cpointer-has-tag? and cpointer-push-tag! operations manage tags to distinguish pointer types.

(_cpointer tag    
  [ptr-type    
  scheme-to-c    
  c-to-scheme])  ctype
  tag : any/c
  ptr-type : ctype? = xpointer
  scheme-to-c : (any/c . -> . any/c) = values
  c-to-scheme : (any/c . -> . any/c) = values
(_cpointer/null tag    
  [ptr-type    
  scheme-to-c    
  c-to-scheme])  ctype
  tag : any/c
  ptr-type : ctype? = xpointer
  scheme-to-c : (any/c . -> . any/c) = values
  c-to-scheme : (any/c . -> . any/c) = values
Construct a kind of a pointer that gets a specific tag when converted to Racket, and accept only such tagged pointers when going to C. An optional ptr-type can be given to be used as the base pointer type, instead of _pointer.

Pointer tags are checked with cpointer-has-tag? and changed with cpointer-push-tag! which means that other tags are preserved. Specifically, if a base ptr-type is given and is itself a _cpointer, then the new type will handle pointers that have the new tag in addition to ptr-type’s tag(s). When the tag is a pair, its first value is used for printing, so the most recently pushed tag which corresponds to the inheriting type will be displayed.

Note that tags are compared with eq? (or memq), which means an interface can hide its value from users (e.g., not provide the cpointer-tag accessor), which makes such pointers un-fake-able.

_cpointer/null is similar to _cpointer except that it tolerates NULL pointers both going to C and back. Note that NULL pointers are represented as #f in Racket, so they are not tagged.

(define-cpointer-type _id)
(define-cpointer-type _id scheme-to-c-expr)
(define-cpointer-type _id scheme-to-c-expr c-to-scheme-expr)
A macro version of _cpointer and _cpointer/null, using the defined name for a tag string, and defining a predicate too. The _id must start with _.

The optional expression produces optional arguments to _cpointer.

In addition to defining _id to a type generated by _cpointer, _id/null is bound to a type produced by _cpointer/null type. Finally, id? is defined as a predicate, and id-tag is defined as an accessor to obtain a tag. The tag is the string form of id.

(cpointer-has-tag? cptr tag)  boolean?
  cptr : any/c
  tag : any/c
(cpointer-push-tag! cptr tag)  void
  cptr : any/c
  tag : any/c
These two functions treat pointer tags as lists of tags. As described in Pointer Functions, a pointer tag does not have any role, except for Racket code that uses it to distinguish pointers; these functions treat the tag value as a list of tags, which makes it possible to construct pointer types that can be treated as other pointer types, mainly for implementing inheritance via upcasts (when a struct contains a super struct as its first element).

The cpointer-has-tag? function checks whether if the given cptr has the tag. A pointer has a tag tag when its tag is either eq? to tag or a list that contains (in the sense of memq) tag.

The cpointer-push-tag! function pushes the given tag value on cptr’s tags. The main properties of this operation are: (a) pushing any tag will make later calls to cpointer-has-tag? succeed with this tag, and (b) the pushed tag will be used when printing the pointer (until a new value is pushed). Technically, pushing a tag will simply set it if there is no tag set, otherwise push it on an existing list or an existing value (treated as a single-element list).