Skip to contents

Functions for allocation, access and registration of foreign C struct and union data type.

Usage

cdata(type)
as.ctype(x, type)
cstruct(sigs, envir=parent.frame())
cunion(sigs, envir=parent.frame())
# S3 method for struct
$(x, index)
# S3 method for struct
$(x, index) <- value
# S3 method for struct
print(x, indent = 0, ...)

Arguments

x

external pointer or atomic raw vector of S3 class 'struct'.

type

S3 typeinfo Object or character string that names the structure type.

sigs

character string that specifies several C struct/union type signatures.

envir

the environment to install S3 type information object(s).

index

character string specifying the field name.

indent

indentation level for pretty printing structures.

value

value to be converted according to struct/union field type given by field index.

...

additional arguments to be passed to print method.

Details

References to foreign C data objects are represented by objects of class 'struct'.

Two reference types are supported:

  • External pointers returned by dyncall using a call signature with a typed pointer return type signature and pointers extracted as a result of unpack and S3 struct $-operators.

  • Internal objects, memory-managed by R, are allocated by cdata: An atomic raw storage object is returned, initialized with length equal to the byte size of the foreign C data type.

In order to access and manipulate the data fields of foreign C aggregate data objects, the “$” and “$<-” S3 operator methods can be used.

S3 objects of class struct have an attribute struct set to the name of a typeinfo object, which provides the run-time type information of a particular foreign C type.

The run-time type information for foreign C struct and union types need to be registered once via cstruct and cunion functions. The C data types are specified by sigs, a signature character string. The formats for both types are described next:

Structure type signatures describe the layout of aggregate struct C data types. Type Signatures are used within the ‘field-types’. ‘field-names’ consists of space separated identifier names and should match the number of fields.

struct-name '{' field-types '}' field-names ';'

Here is an example of a C struct type:


struct Rect {
  signed short x, y;
  unsigned short w, h;
};

The corresponding structure type signature is:

"Rect{ssSS}x y w h;"

Union type signatures describe the components of the union C data type. Type signatures are used within the ‘field-types’. ‘field-names’ consists of space separated identifier names and should match the number of fields.

union-name '|' field-types '}' field-names ';'

Here is an example of a C union type,


union Value {
  int anInt;
  float aFloat;
  struct LongValue aStruct
};

The corresponding union type signature is:

"Value|if<LongValue>}anInt aFloat aStruct;"

as.ctype can be used to cast a foreign C data reference to a different type. When using an external pointer reference, this can lead quickly to a fatal R process crash - like in C.

See also

dyncall for type signatures and typeinfo for details on run-time type information S3 objects.

Examples

# Specify the following foreign type:
# struct Rect {
#     short x, y;
#     unsigned short w, h;
# }
cstruct("Rect{ssSS}x y w h;")
r <- cdata(Rect)
print(r)
#> struct  Rect  {
#>  }
r$x <- 40
#> Error in if (is.na(offset)) stop("unknown field index '", index, "'"): argument is of length zero
r$y <- 60
#> Error in if (is.na(offset)) stop("unknown field index '", index, "'"): argument is of length zero
r$w <- 10
#> Error in if (is.na(offset)) stop("unknown field index '", index, "'"): argument is of length zero
r$h <- 15
#> Error in if (is.na(offset)) stop("unknown field index '", index, "'"): argument is of length zero
print(r)
#> struct  Rect  {
#>  }
str(r)
#>  'struct' raw [1:8] 00 00 00 00 ...
#>  - attr(*, "struct")= chr "Rect"