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.