5.3 Tagged C Pointer Types

► |  | The Racket Foreign Interface

1 | Overview
2 | Loading Foreign Libraries
3 | C Types
4 | Pointer Functions
5 | Derived Utilities
6 | Miscellaneous Support
7 | Unexported Primitive Functions
| Bibliography
| Index

▼ | 5 | Derived Utilities

5.1 | Safe Homogenous Vectors
5.2 | Safe C Vectors
5.3 | Tagged C Pointer Types
5.4 | Serializable C Struct Types
5.5 | Defining Bindings
5.6 | Allocation and Finalization
5.7 | Custodian Shutdown Registration
5.8 | Atomic Execution
5.9 | Speculatively Atomic Execution
5.10 | Thread Scheduling
5.11 | Ports
5.12 | Process-Wide and Place-Wide Registration
5.13 | Operating System Threads
5.14 | Garbage Collection Callbacks
5.15 | Objective-C FFI
5.16 | Cocoa Foundation
5.17 | COM (Common Object Model)
5.18 | File Security-Guard Checks
5.19 | Windows API Helpers

On this page:

_ cpointer
_ cpointer/ null
define-cpointer-type
cpointer-predicate-procedure?
cpointer-has-tag?
cpointer-push-tag!

top ← prev up next →

#### 5.3`` Tagged C Pointer Types

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

> > procedure
> > (_cpointer |  | tag |  |  |  |
> > | [ | ptr-type |  |  |  |
> > |  | racket-to-c |  |  |  |
> > |  | c-to-racket]) |  | → |  | ctype?
> tag : any/c
> ptr-type : (or/c ctype? #f) = _pointer
> racket-to-c : (or/c (any/c . -> . any/c) #f) = values
> c-to-racket : (or/c (any/c . -> . any/c) #f) = values
> (_cpointer/null |  | tag |  |  |  |
> | [ | ptr-type |  |  |  |
> |  | racket-to-c |  |  |  |
> |  | c-to-racket]) |  | → |  | ctype?
> tag : any/c
> ptr-type : (or/c ctype? #f) = _pointer
> racket-to-c : (or/c (any/c . -> . any/c) #f) = values
> c-to-racket : (or/c (any/c . -> . any/c) #f) = values

Constructs a C pointer type, _tag, that gets a specific tag when converted to Racket, and accept only such tagged pointers when going to C. For any optional argument, #f is treated the same as the default value of the argument.

The ptr-type is used as the base pointer type for _tag. Values of ptr-type must be represented as pointers.

Although any value can be used as tag, by convention it is the symbol form of a type name—without a leading underscore. For example, a pointer type _animal would normally use 'animal as the tag.

Pointer tags are checked with cpointer-has-tag? and changed with cpointer-push-tag!, which means that other tags are preserved on an existing pointer value. Specifically, if a base ptr-type is given and is itself produced by _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) is displayed.

A Racket value to be used as a _tag value is first passed to racket-to-c, and the result must be a pointer that is tagged with tag. Similarly, a C value to be returned as a _tag value is initially represented as pointer tagged with tag, but then it is passed to c-to-racket to obtain the Racket representation. Thus, a _tag value is represented by a pointer at the C level, but (unlike the given ptr-type) it can have any representation at the Racket level as implemented by racket-to-c and c-to-racket.

The _cpointer/null function 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.

> syntax (define-cpointer-type _id)
> (define-cpointer-type _id #:tag tag-expr)
> (define-cpointer-type _id ptr-type-expr)
> (define-cpointer-type _id ptr-type-expr #:tag tag-expr)
> (define-cpointer-type _id ptr-type-expr
> racket-to-c-expr c-to-racket-expr)
> (define-cpointer-type _id ptr-type-expr
> racket-to-c-expr c-to-racket-expr
> #:tag tag-expr)

A macro version of _cpointer and _cpointer/null, using the defined name for a tag symbol, and defining a predicate too. The _id must start with _.

The optional expressions produce 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. If provided, the tag is tag-expr, otherwise it is the symbol form of id.

> procedure (cpointer-predicate-procedure? v) → boolean?
> v : any/c

Returns #t if v is a predicate procedure generated by define-cpointer-type or define-cstruct, #f otherwise.

Added in version 6.6.0.1 of package base.

> procedure (cpointer-has-tag? cptr tag) → boolean?
> cptr : cpointer?
> tag : any/c
> (cpointer-push-tag! cptr tag) → void?
> cptr : cpointer?
> 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).

top ← prev up next →