This class aims at defining a struct layout.
static VALUE struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align) { StructLayout* layout; ffi_type* ltype; int i; Data_Get_Struct(self, StructLayout, layout); layout->fieldCount = (int) RARRAY_LEN(fields); layout->rbFieldMap = rb_hash_new(); 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 *)); 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); Data_Get_Struct(rbField, StructField, 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; st_insert(layout->fieldSymbolTable, rbName, rbField); 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"); } return self; }
static VALUE struct_layout_aref(VALUE self, VALUE field) { StructLayout* layout; Data_Get_Struct(self, StructLayout, layout); return rb_hash_aref(layout->rbFieldMap, field); }
static VALUE struct_layout_union_bang(VALUE self) { static 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; Data_Get_Struct(self, StructLayout, 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; }
static VALUE struct_layout_fields(VALUE self) { StructLayout* layout; Data_Get_Struct(self, StructLayout, layout); return rb_ary_dup(layout->rbFields); }
static VALUE struct_layout_members(VALUE self) { StructLayout* layout; Data_Get_Struct(self, StructLayout, layout); return rb_ary_dup(layout->rbFieldNames); }
@return [Numeric] Get the offset of a field.
# File lib/ffi/struct.rb, line 38 def offset_of(field_name) self[field_name].offset end
@return [Array<Array(Symbol, Numeric)> Get an array of tuples (field name, offset of the field).
# File lib/ffi/struct.rb, line 32 def offsets members.map { |m| [ m, self[m].offset ] } end
Generated with the Darkfish Rdoc Generator 2.