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) ⇒ Numeric
Get the offset of a field.
-
#offsets ⇒ Array<Array(Symbol, Numeric)>
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.
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'ext/ffi_c/StructLayout.c', line 439
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;
}
|
Instance Method Details
#[](field) ⇒ Object
544 545 546 547 548 549 550 551 552 |
# File 'ext/ffi_c/StructLayout.c', line 544
static VALUE
struct_layout_aref(VALUE self, VALUE field)
{
StructLayout* layout;
Data_Get_Struct(self, StructLayout, layout);
return rb_hash_aref(layout->rbFieldMap, field);
}
|
#[](field) ⇒ StructLayout::Field
Get a field from the layout.
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 |
# File 'ext/ffi_c/StructLayout.c', line 510
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;
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;
}
|
#fields ⇒ Array<StructLayout::Field>
Get fields list.
559 560 561 562 563 564 565 566 567 |
# File 'ext/ffi_c/StructLayout.c', line 559
static VALUE
struct_layout_fields(VALUE self)
{
StructLayout* layout;
Data_Get_Struct(self, StructLayout, layout);
return rb_ary_dup(layout->rbFields);
}
|
#members ⇒ Array<Symbol>
Get list of field names.
574 575 576 577 578 579 580 581 582 |
# File 'ext/ffi_c/StructLayout.c', line 574
static VALUE
struct_layout_members(VALUE self)
{
StructLayout* layout;
Data_Get_Struct(self, StructLayout, layout);
return rb_ary_dup(layout->rbFieldNames);
}
|
#offset_of(field_name) ⇒ Numeric
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, Numeric)>
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.
589 590 591 592 593 594 595 596 597 |
# File 'ext/ffi_c/StructLayout.c', line 589
static VALUE
struct_layout_to_a(VALUE self)
{
StructLayout* layout;
Data_Get_Struct(self, StructLayout, layout);
return rb_ary_dup(layout->rbFields);
}
|