Class: FFI::StructLayout

### Home Classes Methods

### In Files

- lib/ffi/struct.rb
- ext/ffi_c/ffi.c

### Parent

FFI::Type

### Namespace

- CLASS FFI::StructLayout::Array
- CLASS FFI::StructLayout::Enum
- CLASS FFI::StructLayout::Field
- CLASS FFI::StructLayout::Function
- CLASS FFI::StructLayout::InnerStruct
- CLASS FFI::StructLayout::Mapped
- CLASS FFI::StructLayout::Number
- CLASS FFI::StructLayout::Pointer
- CLASS FFI::StructLayout::String

### Methods

- ::new
- #[]
- #__union!
- #fields
- #members
- #offset_of
- #offsets
- #to_a

### Files

- Makefile
- LICENSE
- compile
- configure
- depcomp
- stamp-vti
- install-sh
- libtool-version
- mdate-sh
- missing

### Class/Module Index

Quicksearch

- FFI
- FFI::AutoPointer
- FFI::AutoPointer::CallableReleaser
- FFI::AutoPointer::DefaultReleaser
- FFI::AutoPointer::Releaser
- FFI::ConstGenerator
- FFI::ConstGenerator::Constant
- FFI::Enum
- FFI::Enums
- FFI::Function
- FFI::FunctionType
- FFI::Generator
- FFI::Generator::Task
- FFI::IO
- FFI::LastError
- FFI::ManagedStruct
- FFI::MemoryPointer
- FFI::NativeType
- FFI::Platform
- FFI::PlatformError
- FFI::Pointer
- FFI::StrPtrConverter
- FFI::Struct
- FFI::Struct::InlineArray
- FFI::Struct::ManagedStructConverter
- FFI::StructByReference
- FFI::StructByValue
- FFI::StructGenerator
- FFI::StructGenerator::Field
- FFI::StructLayout
- FFI::StructLayout::Array
- FFI::StructLayout::Enum
- FFI::StructLayout::Field
- FFI::StructLayout::Function
- FFI::StructLayout::InnerStruct
- FFI::StructLayout::Mapped
- FFI::StructLayout::Number
- FFI::StructLayout::Pointer
- FFI::StructLayout::String
- FFI::StructLayoutBuilder
- FFI::Type
- FFI::Type::Builtin
- FFI::TypesGenerator
- FFI::Union
- FFI::VariadicInvoker

No matching classes.

# FFI::StructLayout

This class aims at defining a struct layout.

### Public Class Methods

initialize(fields, size, align) click to toggle source
@param [Array] fields
@param [Numeric] size
@param [Numeric] align
@return [self]
A new StructLayout instance.

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

### Public Instance Methods

[](p1) click to toggle source

    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) click to toggle source
@param [Symbol] field
@return [StructLayout::Field]
Get a field from the layout.

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

fields click to toggle source
@return [Array]
Get fields list.

    static VALUE
    struct_layout_fields(VALUE self)
    {
        StructLayout* layout;

        Data_Get_Struct(self, StructLayout, layout);

        return rb_ary_dup(layout->rbFields);
    }

members click to toggle source
@return [Array]
Get list of field names.

    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) click to toggle source

@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

offsets() click to toggle source

@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

to_a click to toggle source
@return [Array]
Get an array of fields.

    static VALUE
    struct_layout_to_a(VALUE self)
    {
        StructLayout* layout;

        Data_Get_Struct(self, StructLayout, layout);

        return rb_ary_dup(layout->rbFields);
    }

[Validate]

Generated with the Darkfish Rdoc Generator 2.