Class: FFI::StructLayout
- Defined in:
- ext/ffi_c/StructLayout.c,
lib/ffi/struct_layout.rb,
ext/ffi_c/StructLayout.c
Overview
This class aims at defining a struct layout.
Defined Under Namespace
Classes: Array, CharArray, Enum, Field, Function, InnerStruct, Mapped, Number, Pointer, String
Constant Summary
Constants inherited from Type
Instance Method Summary collapse
- #[](field) ⇒ Object
-
#[](field) ⇒ StructLayout::Field
Get a field from the layout.
-
#fields ⇒ Array<StructLayout::Field>
Get fields list.
-
#initialize(fields, size, align) ⇒ self
constructor
A new StructLayout instance.
-
#members ⇒ Array<Symbol>
Get list of field names.
-
#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 ⇒ Array<StructLayout::Field>
Get an array of fields.
Methods inherited from Type
Constructor Details
#initialize(fields, size, align) ⇒ self
A new StructLayout instance.
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
# 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) ⇒ Object
591 592 593 594 595 596 597 598 599 |
# 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) ⇒ StructLayout::Field
Get a field from the layout.
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 |
# 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 ⇒ Array<StructLayout::Field>
Get fields list.
606 607 608 609 610 611 612 613 614 |
# 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 ⇒ Array<Symbol>
Get list of field names.
621 622 623 624 625 626 627 628 629 |
# 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.
46 47 48 |
# 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).
40 41 42 |
# File 'lib/ffi/struct_layout.rb', line 40 def offsets members.map { |m| [ m, self[m].offset ] } end |
#to_a ⇒ Array<StructLayout::Field>
Get an array of fields.
636 637 638 639 640 641 642 643 644 |
# 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);
}
|