2.3 Compound Foreign Types
foreign type | ||||||||
| ||||||||
| ||||||||
definition | ||||||||
| ||||||||
| ||||||||
|
Each field_id must be distinct, and the corresponding field_type describes the field’s representation on the C side and the representation used on the Rhombus side if the field’s value is extracted from a representation of the struct type.
The foreign.struct form defines id as an alias for the corresponding struct type using id like maybe_tag for a pointer tag. The id is also defined for additional roles:
The id is defined as an annotation that recognizes pointers tagged with id.
The id is defined as a veneer, and id as a type implies the static information of id as a veneer. Each field_id is bound as a field of the veneer that can be used to access or update the corresponding field in an instance of the struct.
When a field is accessed, the result is a representation of the corresponding C field value based on the conversion implied by the associated field_type.
When the field is set using := to a Rhombus value, a value converted to C based on the associated field_type, and that C value is installed into the struct instance.
The id is defined for use with new allocate to an instance of the struct with field values provided as arguments (in addition to the possibility of using id by itself as a type to create an uninitialized instance).
Note that the Racket-side representation is the same for id and id*, even though the C-side representation differs.
foreign.struct point_t(x :: double_t,
> sizeof(point_t)
16
8
> p1
#<point_t*/gcable>
> p1 is_a point_t
#true
> p1 is_a foreign.type point_t*
#true
> p1.x
1.0
> p1.y
2.0
> p1.x
5.0
> point_t.x(p1)
5.0
point_t.x: not an instance for method call
value: #<ptr_t/gcable>
With this example’s definition of point_t, a field in another struct type would take up 16 bytes, while a point_t* field would take up 8 bytes. Accessing the field in either case would produce a Racket representation that is a pointer tagged as point_t*. In the case of a point_t field, the returned pointer would refer to memory within the accessed struct instance.
Along similar lines, a pointer tagged with point_t* is suitable as an argument to a C function that has either a point_t or point_t* argument. In the case of a point_t argument, the C function receives a copy of the content of the pointer. In the case of a point_t* argument, the C function receives the same address as encapsulated by the pointer.
foreign type | ||||
| ||||
| ||||
definition | ||||
|
The use of a defined id with new plus arguments is different than for a type defined with foreign.struct, since a foreign.union instance is a variant for only one of the fields, not a composite value with all of the fields. To specify the relevant variant, there must be only one argument, and it must be in a block that is prefixed with the relevant $field_id.
foreign.union grade_t (score :: double_t,
foreign type | ||||||||
| ||||||||
foreign type | ||||||||
| ||||||||
|
When converting from Rhombus to C, memory is allocated using
new, maybe_mode, and the length of the list or
array. A ~length specification is used only when converting
from C back to Rhombus, since a elem_type* does not encode a
length. If ~length is not provided, it defaults to
0—
foreign type | |
| |
foreign type | |
| |
foreign type | |
A type form (type) is equivalent to type.
A (arg, ...) or (arg, ..., ~varargs, arg, ...) form is allowed as a “type” only on the left-hand side of the -> operator.