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); }