Class: FFI::StructLayout

Inherits:
Type
  • Object
show all
Defined in:
lib/ffi/struct.rb,
ext/ffi_c/StructLayout.c

Defined Under Namespace

Classes: Array, Field, Function, StructByValue

Constant Summary

Constants inherited from Type

Type::Array, Type::Function, Type::Struct

Instance Method Summary collapse

Constructor Details

#initialize(field_names, fields, size, align) ⇒ Object



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'ext/ffi_c/StructLayout.c', line 291

static VALUE
struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size, VALUE align)
{
    StructLayout* layout;
    ffi_type* ltype;
    int i;

    Data_Get_Struct(self, StructLayout, layout);
    layout->rbFieldMap = rb_hash_new();
    layout->rbFieldNames = rb_ary_dup(field_names);
    layout->size = NUM2INT(size);
    layout->align = NUM2INT(align);
    layout->fieldCount = RARRAY_LEN(field_names);
    layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
    layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
    layout->rbFields = rb_ary_new2(layout->fieldCount);
    layout->base.ffiType->elements = layout->ffiTypes;
    layout->base.ffiType->size = 0;
    layout->base.ffiType->alignment = 1;

    ltype = layout->base.ffiType;
    for (i = 0; i < layout->fieldCount; ++i) {
        VALUE rbName = rb_ary_entry(field_names, i);
        VALUE rbField = rb_hash_aref(fields, 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);
        }

        Data_Get_Struct(rbField, StructField, field = layout->fields[i]);

        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) {
            rb_raise(rb_eTypeError, "type of field %d has zero size", i);
        }

        rb_hash_aset(layout->rbFieldMap, rbName, rbField);
        layout->ffiTypes[i] = ftype;
        rb_ary_push(layout->rbFields, rbField);
        ltype->size = MAX(ltype->size, field->offset + ftype->size);
        ltype->alignment = MAX(ltype->alignment, ftype->alignment);
    }

    if (ltype->size == 0) {
        rb_raise(rb_eRuntimeError, "Struct size is zero");
    }

    // Include tail padding
    ltype->size = FFI_ALIGN(ltype->size, ltype->alignment);

    return self;
}

Instance Method Details

#[](field) ⇒ Object



351
352
353
354
355
356
357
358
359
# File 'ext/ffi_c/StructLayout.c', line 351

static VALUE
struct_layout_aref(VALUE self, VALUE field)
{
    StructLayout* layout;

    Data_Get_Struct(self, StructLayout, layout);

    return rb_hash_aref(layout->rbFieldMap, field);
}

#fieldsObject



361
362
363
364
365
366
367
368
369
# File 'ext/ffi_c/StructLayout.c', line 361

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

    Data_Get_Struct(self, StructLayout, layout);

    return rb_ary_dup(layout->rbFields);
}

#membersObject



371
372
373
374
375
376
377
378
379
# File 'ext/ffi_c/StructLayout.c', line 371

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) ⇒ Object



10
11
12
# File 'lib/ffi/struct.rb', line 10

def offset_of(field_name)
  self[field_name].offset
end

#offsetsObject



6
7
8
# File 'lib/ffi/struct.rb', line 6

def offsets
  members.map { |m| [ m, self[m].offset ] }
end

#to_aObject



381
382
383
384
385
386
387
388
389
# File 'ext/ffi_c/StructLayout.c', line 381

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

    Data_Get_Struct(self, StructLayout, layout);

    return rb_ary_dup(layout->rbFields);
}