Class: FFI::StructLayout
| Relationships & Source Files | |
| Namespace Children | |
|
Classes:
| |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
Type
|
|
|
Instance Chain:
self,
Type
|
|
| Inherits: | FFI::Type |
| Defined in: | ext/ffi_c/StructLayout.c, lib/ffi/struct_layout.rb |
Overview
This class aims at defining a struct layout.
Constant Summary
Class Method Summary
Instance Method Summary
- #[](field)
- #[](field)
- #fields
- #members
-
#offset_of(field_name) ⇒ Integer
Get the offset of a field.
-
#offsets ⇒ Array<Array(Symbol, Integer)>
Get an array of tuples (field name, offset of the field).
- #to_a ⇒ ?
Type - Inherited
Constructor Details
.new(fields, size, align)
.new(StructLayout)
# File 'ext/ffi_c/StructLayout.c', line 482
static VALUE
struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
{
StructLayout* layout;
ffi_type* ltype;
int i;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
layout->fieldCount = RARRAY_LENINT(fields);
RB_OBJ_WRITE(self, &layout->rbFieldMap, rb_hash_new());
RB_OBJ_WRITE(self, &layout->rbFieldNames, rb_ary_new2(layout->fieldCount));
layout->size = (int) FFI_ALIGN(NUM2INT(size), NUM2INT(align));
layout->align = NUM2INT(align);
layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
RB_OBJ_WRITE(self, &layout->rbFields, rb_ary_new2(layout->fieldCount));
layout->referenceFieldCount = 0;
layout->base.ffiType->elements = layout->ffiTypes;
layout->base.ffiType->size = layout->size;
layout->base.ffiType->alignment = layout->align;
ltype = layout->base.ffiType;
for (i = 0; i < (int) layout->fieldCount; ++i) {
VALUE rbField = rb_ary_entry(fields, i);
VALUE rbName;
StructField* field;
ffi_type* ftype;
if (!rb_obj_is_kind_of(rbField, rbffi_StructLayoutFieldClass)) {
rb_raise(rb_eTypeError, "wrong type for field %d.", i);
}
rbName = rb_funcall2(rbField, rb_intern("name"), 0, NULL);
TypedData_Get_Struct(rbField, StructField, &rbffi_struct_field_data_type, field);
layout->fields[i] = field;
if (field->type == NULL || field->type->ffiType == NULL) {
rb_raise(rb_eRuntimeError, "type of field %d not supported", i);
}
ftype = field->type->ffiType;
if (ftype->size == 0 && i < ((int) layout->fieldCount - 1)) {
rb_raise(rb_eTypeError, "type of field %d has zero size", i);
}
if (field->referenceRequired) {
field->referenceIndex = layout->referenceFieldCount++;
}
layout->ffiTypes[i] = ftype->size > 0 ? ftype : NULL;
rb_hash_aset(layout->rbFieldMap, rbName, rbField);
rb_ary_push(layout->rbFields, rbField);
rb_ary_push(layout->rbFieldNames, rbName);
}
if (ltype->size == 0) {
rb_raise(rb_eRuntimeError, "Struct size is zero");
}
rb_obj_freeze(layout->rbFieldMap);
rb_obj_freeze(layout->rbFields);
rb_obj_freeze(layout->rbFieldNames);
rb_obj_freeze(self);
return self;
}
Instance Method Details
#[](field)
[ GitHub ]# File 'ext/ffi_c/StructLayout.c', line 591
static VALUE
struct_layout_aref(VALUE self, VALUE field)
{
StructLayout* layout;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
return rb_hash_aref(layout->rbFieldMap, field);
}
#[](field)
#a(field)
# File 'ext/ffi_c/StructLayout.c', line 557
static VALUE
struct_layout_union_bang(VALUE self)
{
const ffi_type *alignment_types[] = { &ffi_type_sint8, &ffi_type_sint16, &ffi_type_sint32, &ffi_type_sint64,
&ffi_type_float, &ffi_type_double, &ffi_type_longdouble, NULL };
StructLayout* layout;
ffi_type *t = NULL;
int count, i;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
for (i = 0; alignment_types[i] != NULL; ++i) {
if (alignment_types[i]->alignment == layout->align) {
t = (ffi_type *) alignment_types[i];
break;
}
}
if (t == NULL) {
rb_raise(rb_eRuntimeError, "cannot create libffi union representation for alignment %d", layout->align);
return Qnil;
}
count = (int) layout->size / (int) t->size;
xfree(layout->ffiTypes);
layout->ffiTypes = xcalloc(count + 1, sizeof(ffi_type *));
layout->base.ffiType->elements = layout->ffiTypes;
for (i = 0; i < count; ++i) {
layout->ffiTypes[i] = t;
}
return self;
}
#fields
#fields(list)
# File 'ext/ffi_c/StructLayout.c', line 606
static VALUE
struct_layout_fields(VALUE self)
{
StructLayout* layout;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
return rb_ary_dup(layout->rbFields);
}
#members
#list(of)
# File 'ext/ffi_c/StructLayout.c', line 621
static VALUE
struct_layout_members(VALUE self)
{
StructLayout* layout;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
return rb_ary_dup(layout->rbFieldNames);
}
#offset_of(field_name) ⇒ Integer
Get the offset of a field.
# File 'lib/ffi/struct_layout.rb', line 46
def offset_of(field_name) self[field_name].offset end
#offsets ⇒ Array<Array(Symbol, Integer)>
Get an array of tuples (field name, offset of the field).
# File 'lib/ffi/struct_layout.rb', line 40
def offsets members.map { |m| [ m, self[m].offset ] } end
#to_a ⇒ ?
#an(array)
# File 'ext/ffi_c/StructLayout.c', line 636
static VALUE
struct_layout_to_a(VALUE self)
{
StructLayout* layout;
TypedData_Get_Struct(self, StructLayout, &rbffi_struct_layout_data_type, layout);
return rb_ary_dup(layout->rbFields);
}