ffi 0.4.0-x86-mswin32 → 0.5.0-x86-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/README.rdoc +15 -15
- data/Rakefile +57 -8
- data/ext/ffi_c/AbstractMemory.c +101 -24
- data/ext/ffi_c/AbstractMemory.h +98 -6
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +1 -0
- data/ext/ffi_c/Buffer.c +59 -43
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +3 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +30 -6
- data/ext/ffi_c/MemoryPointer.c +50 -28
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Pointer.c +73 -13
- data/ext/ffi_c/Pointer.h +31 -7
- data/ext/ffi_c/Struct.c +517 -224
- data/ext/ffi_c/Struct.h +60 -6
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +121 -22
- data/ext/ffi_c/Type.h +37 -8
- data/ext/ffi_c/Types.c +46 -61
- data/ext/ffi_c/Types.h +38 -7
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +53 -3
- data/ext/ffi_c/extconf.rb +6 -7
- data/ext/ffi_c/ffi.c +45 -39
- data/ext/ffi_c/libffi.darwin.mk +2 -2
- data/ext/ffi_c/rbffi.h +3 -0
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
- data/lib/ffi/ffi.rb +7 -4
- data/lib/ffi/library.rb +34 -59
- data/lib/ffi/platform.rb +14 -4
- data/lib/ffi/struct.rb +110 -281
- data/lib/ffi/union.rb +4 -9
- data/lib/ffi/variadic.rb +1 -6
- data/spec/ffi/buffer_spec.rb +6 -0
- data/spec/ffi/callback_spec.rb +34 -3
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +56 -52
- data/spec/ffi/pointer_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +26 -3
- data/spec/ffi/struct_spec.rb +56 -3
- metadata +34 -13
- data/ext/ffi_c/Callback.c +0 -374
- data/ext/ffi_c/Callback.h +0 -47
- data/ext/ffi_c/Invoker.c +0 -962
- data/ext/ffi_c/NullPointer.c +0 -143
    
        data/ext/ffi_c/Pointer.h
    CHANGED
    
    | @@ -1,6 +1,33 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 1 | 
            +
            /*
         | 
| 2 | 
            +
             * Copyright (c) 2008, 2009, Wayne Meissner
         | 
| 3 | 
            +
             *
         | 
| 4 | 
            +
             * All rights reserved.
         | 
| 5 | 
            +
             *
         | 
| 6 | 
            +
             * Redistribution and use in source and binary forms, with or without
         | 
| 7 | 
            +
             * modification, are permitted provided that the following conditions are met:
         | 
| 8 | 
            +
             *
         | 
| 9 | 
            +
             * * Redistributions of source code must retain the above copyright notice, this
         | 
| 10 | 
            +
             *   list of conditions and the following disclaimer.
         | 
| 11 | 
            +
             * * Redistributions in binary form must reproduce the above copyright notice
         | 
| 12 | 
            +
             *   this list of conditions and the following disclaimer in the documentation
         | 
| 13 | 
            +
             *   and/or other materials provided with the distribution.
         | 
| 14 | 
            +
             * * The name of the author or authors may not be used to endorse or promote
         | 
| 15 | 
            +
             *   products derived from this software without specific prior written permission.
         | 
| 16 | 
            +
             *
         | 
| 17 | 
            +
             * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         | 
| 18 | 
            +
             * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         | 
| 19 | 
            +
             * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         | 
| 20 | 
            +
             * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
         | 
| 21 | 
            +
             * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         | 
| 22 | 
            +
             * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         | 
| 23 | 
            +
             * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         | 
| 24 | 
            +
             * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         | 
| 25 | 
            +
             * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         | 
| 26 | 
            +
             * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 27 | 
            +
             */
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            #ifndef RBFFI_POINTER_H
         | 
| 30 | 
            +
            #define	RBFFI_POINTER_H
         | 
| 4 31 |  | 
| 5 32 | 
             
            #ifdef	__cplusplus
         | 
| 6 33 | 
             
            extern "C" {
         | 
| @@ -9,17 +36,14 @@ extern "C" { | |
| 9 36 | 
             
            #include "AbstractMemory.h"
         | 
| 10 37 |  | 
| 11 38 | 
             
            extern void rbffi_Pointer_Init(VALUE moduleFFI);
         | 
| 12 | 
            -
            extern void rbffi_NullPointer_Init(VALUE moduleFFI);
         | 
| 13 39 | 
             
            extern VALUE rbffi_Pointer_NewInstance(void* addr);
         | 
| 14 40 | 
             
            extern VALUE rbffi_PointerClass;
         | 
| 15 | 
            -
            extern VALUE rbffi_NullPointerClass;
         | 
| 16 41 | 
             
            extern VALUE rbffi_NullPointerSingleton;
         | 
| 17 | 
            -
            extern MemoryOps rbffi_NullPointerOps;
         | 
| 18 42 |  | 
| 19 43 |  | 
| 20 44 | 
             
            #ifdef	__cplusplus
         | 
| 21 45 | 
             
            }
         | 
| 22 46 | 
             
            #endif
         | 
| 23 47 |  | 
| 24 | 
            -
            #endif	/*  | 
| 48 | 
            +
            #endif	/* RBFFI_POINTER_H */
         | 
| 25 49 |  | 
    
        data/ext/ffi_c/Struct.c
    CHANGED
    
    | @@ -1,4 +1,35 @@ | |
| 1 | 
            +
            /*
         | 
| 2 | 
            +
             * Copyright (c) 2008, 2009, Wayne Meissner
         | 
| 3 | 
            +
             * Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
         | 
| 4 | 
            +
             *
         | 
| 5 | 
            +
             * All rights reserved.
         | 
| 6 | 
            +
             *
         | 
| 7 | 
            +
             * Redistribution and use in source and binary forms, with or without
         | 
| 8 | 
            +
             * modification, are permitted provided that the following conditions are met:
         | 
| 9 | 
            +
             *
         | 
| 10 | 
            +
             * * Redistributions of source code must retain the above copyright notice, this
         | 
| 11 | 
            +
             *   list of conditions and the following disclaimer.
         | 
| 12 | 
            +
             * * Redistributions in binary form must reproduce the above copyright notice
         | 
| 13 | 
            +
             *   this list of conditions and the following disclaimer in the documentation
         | 
| 14 | 
            +
             *   and/or other materials provided with the distribution.
         | 
| 15 | 
            +
             * * The name of the author or authors may not be used to endorse or promote
         | 
| 16 | 
            +
             *   products derived from this software without specific prior written permission.
         | 
| 17 | 
            +
             *
         | 
| 18 | 
            +
             * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         | 
| 19 | 
            +
             * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         | 
| 20 | 
            +
             * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         | 
| 21 | 
            +
             * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
         | 
| 22 | 
            +
             * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         | 
| 23 | 
            +
             * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         | 
| 24 | 
            +
             * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         | 
| 25 | 
            +
             * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         | 
| 26 | 
            +
             * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         | 
| 27 | 
            +
             * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 28 | 
            +
             */
         | 
| 29 | 
            +
             | 
| 1 30 | 
             
            #include <sys/types.h>
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            #include "Function.h"
         | 
| 2 33 | 
             
            #include <sys/param.h>
         | 
| 3 34 | 
             
            #include <stdint.h>
         | 
| 4 35 | 
             
            #include <stdbool.h>
         | 
| @@ -8,117 +39,46 @@ | |
| 8 39 | 
             
            #include "AbstractMemory.h"
         | 
| 9 40 | 
             
            #include "Pointer.h"
         | 
| 10 41 | 
             
            #include "MemoryPointer.h"
         | 
| 42 | 
            +
            #include "Function.h"
         | 
| 11 43 | 
             
            #include "Types.h"
         | 
| 12 44 | 
             
            #include "Struct.h"
         | 
| 45 | 
            +
            #include "StructByValue.h"
         | 
| 46 | 
            +
            #include "ArrayType.h"
         | 
| 13 47 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
                unsigned int type;
         | 
| 16 | 
            -
                unsigned int offset;
         | 
| 17 | 
            -
                unsigned int size;
         | 
| 18 | 
            -
                unsigned int align;
         | 
| 19 | 
            -
            } StructField;
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            typedef struct StructLayout {
         | 
| 22 | 
            -
                VALUE rbFields;
         | 
| 23 | 
            -
                unsigned int fieldCount;
         | 
| 24 | 
            -
                int size;
         | 
| 25 | 
            -
                int align;
         | 
| 26 | 
            -
            } StructLayout;
         | 
| 48 | 
            +
            #define FFI_ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)
         | 
| 27 49 |  | 
| 28 50 | 
             
            typedef struct StructLayoutBuilder {
         | 
| 29 | 
            -
                 | 
| 51 | 
            +
                VALUE rbFieldNames;
         | 
| 52 | 
            +
                VALUE rbFieldMap;
         | 
| 53 | 
            +
                unsigned int size;
         | 
| 54 | 
            +
                unsigned int alignment;
         | 
| 55 | 
            +
                bool isUnion;
         | 
| 30 56 | 
             
            } StructLayoutBuilder;
         | 
| 31 57 |  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
            VALUE rbffi_StructClass = Qnil;
         | 
| 37 | 
            -
            static VALUE StructLayoutClass = Qnil;
         | 
| 38 | 
            -
            static VALUE StructFieldClass = Qnil, StructLayoutBuilderClass = Qnil;
         | 
| 39 | 
            -
            static ID pointer_var_id = 0, layout_var_id = 0, SIZE_ID, ALIGN_ID, TYPE_ID;
         | 
| 40 | 
            -
            static ID get_id = 0, put_id = 0, to_ptr = 0, to_s = 0, layout_id = 0;
         | 
| 41 | 
            -
             | 
| 42 | 
            -
            static VALUE
         | 
| 43 | 
            -
            struct_field_allocate(VALUE klass)
         | 
| 44 | 
            -
            {
         | 
| 45 | 
            -
                StructField* field;
         | 
| 46 | 
            -
                return Data_Make_Struct(klass, StructField, NULL, -1, field);
         | 
| 47 | 
            -
            }
         | 
| 58 | 
            +
            typedef struct InlineArray_ {
         | 
| 59 | 
            +
                VALUE rbMemory;
         | 
| 60 | 
            +
                VALUE rbField;
         | 
| 48 61 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
            struct_field_initialize(int argc, VALUE* argv, VALUE self)
         | 
| 51 | 
            -
            {
         | 
| 52 | 
            -
                VALUE offset = Qnil, info = Qnil;
         | 
| 62 | 
            +
                AbstractMemory* memory;
         | 
| 53 63 | 
             
                StructField* field;
         | 
| 54 | 
            -
                 | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                nargs = rb_scan_args(argc, argv, "11", &offset, &info);
         | 
| 59 | 
            -
                
         | 
| 60 | 
            -
                field->offset = NUM2UINT(offset);
         | 
| 61 | 
            -
                if (rb_const_defined(CLASS_OF(self), TYPE_ID)) {
         | 
| 62 | 
            -
                    field->type = NUM2UINT(rb_const_get(CLASS_OF(self), TYPE_ID));
         | 
| 63 | 
            -
                } else {
         | 
| 64 | 
            -
                    field->type = ~0;
         | 
| 65 | 
            -
                }
         | 
| 66 | 
            -
             | 
| 67 | 
            -
            #ifdef notyet
         | 
| 68 | 
            -
                field->size = NUM2UINT(rb_const_get(klass, SIZE_ID));
         | 
| 69 | 
            -
                field->align = NUM2UINT(rb_const_get(klass, ALIGN_ID));
         | 
| 70 | 
            -
            #endif
         | 
| 71 | 
            -
                rb_iv_set(self, "@off", offset);
         | 
| 72 | 
            -
                rb_iv_set(self, "@info", info);
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                return self;
         | 
| 75 | 
            -
            }
         | 
| 64 | 
            +
                MemoryOp *op;
         | 
| 65 | 
            +
                Type* componentType;
         | 
| 66 | 
            +
            } InlineArray;
         | 
| 76 67 |  | 
| 77 | 
            -
            static VALUE
         | 
| 78 | 
            -
            struct_field_offset(VALUE self)
         | 
| 79 | 
            -
            {
         | 
| 80 | 
            -
                StructField* field;
         | 
| 81 | 
            -
                Data_Get_Struct(self, StructField, field);
         | 
| 82 | 
            -
                return UINT2NUM(field->offset);
         | 
| 83 | 
            -
            }
         | 
| 84 68 |  | 
| 85 | 
            -
            static  | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
                MemoryOp* op;
         | 
| 90 | 
            -
                AbstractMemory* memory = MEMORY(pointer);
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                Data_Get_Struct(self, StructField, f);
         | 
| 93 | 
            -
                op = ptr_get_op(memory, f->type);
         | 
| 94 | 
            -
                if (op == NULL) {
         | 
| 95 | 
            -
                    VALUE name = rb_class_name(CLASS_OF(self));
         | 
| 96 | 
            -
                    rb_raise(rb_eArgError, "get not supported for %s", StringValueCStr(name));
         | 
| 97 | 
            -
                    return Qnil;
         | 
| 98 | 
            -
                }
         | 
| 69 | 
            +
            static void struct_mark(Struct *);
         | 
| 70 | 
            +
            static void struct_layout_builder_mark(StructLayoutBuilder *);
         | 
| 71 | 
            +
            static void struct_layout_builder_free(StructLayoutBuilder *);
         | 
| 72 | 
            +
            static void inline_array_mark(InlineArray *);
         | 
| 99 73 |  | 
| 100 | 
            -
             | 
| 101 | 
            -
            }
         | 
| 74 | 
            +
            static inline int align(int offset, int align);
         | 
| 102 75 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
            {
         | 
| 106 | 
            -
                StructField* f;
         | 
| 107 | 
            -
                MemoryOp* op;
         | 
| 108 | 
            -
                AbstractMemory* memory = MEMORY(pointer);
         | 
| 76 | 
            +
            VALUE rbffi_StructClass = Qnil;
         | 
| 77 | 
            +
            static VALUE StructLayoutBuilderClass = Qnil;
         | 
| 109 78 |  | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
                    VALUE name = rb_class_name(CLASS_OF(self));
         | 
| 114 | 
            -
                    rb_raise(rb_eArgError, "put not supported for %s", StringValueCStr(name));
         | 
| 115 | 
            -
                    return self;
         | 
| 116 | 
            -
                }
         | 
| 117 | 
            -
                
         | 
| 118 | 
            -
                (*op->put)(memory, f->offset, value);
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                return self;
         | 
| 121 | 
            -
            }
         | 
| 79 | 
            +
            VALUE rbffi_StructInlineArrayClass = Qnil;
         | 
| 80 | 
            +
            static ID id_pointer_ivar = 0, id_layout_ivar = 0;
         | 
| 81 | 
            +
            static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0;
         | 
| 122 82 |  | 
| 123 83 | 
             
            static inline char*
         | 
| 124 84 | 
             
            memory_address(VALUE self)
         | 
| @@ -151,14 +111,14 @@ struct_initialize(int argc, VALUE* argv, VALUE self) | |
| 151 111 |  | 
| 152 112 | 
             
                /* Call up into ruby code to adjust the layout */
         | 
| 153 113 | 
             
                if (nargs > 1) {
         | 
| 154 | 
            -
                    s->rbLayout = rb_funcall2(CLASS_OF(self),  | 
| 155 | 
            -
                } else if (rb_cvar_defined(klass,  | 
| 156 | 
            -
                    s->rbLayout = rb_cvar_get(klass,  | 
| 114 | 
            +
                    s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
         | 
| 115 | 
            +
                } else if (rb_cvar_defined(klass, id_layout_ivar)) {
         | 
| 116 | 
            +
                    s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
         | 
| 157 117 | 
             
                } else {
         | 
| 158 118 | 
             
                    rb_raise(rb_eRuntimeError, "No Struct layout configured");
         | 
| 159 119 | 
             
                }
         | 
| 160 120 |  | 
| 161 | 
            -
                if (!rb_obj_is_kind_of(s->rbLayout,  | 
| 121 | 
            +
                if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
         | 
| 162 122 | 
             
                    rb_raise(rb_eRuntimeError, "Invalid Struct layout");
         | 
| 163 123 | 
             
                }
         | 
| 164 124 |  | 
| @@ -196,53 +156,17 @@ struct_field(Struct* s, VALUE fieldName) | |
| 196 156 | 
             
                    rb_raise(rb_eRuntimeError, "layout not set for Struct");
         | 
| 197 157 | 
             
                }
         | 
| 198 158 |  | 
| 199 | 
            -
                rbField = rb_hash_aref(layout-> | 
| 159 | 
            +
                rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
         | 
| 200 160 | 
             
                if (rbField == Qnil) {
         | 
| 201 | 
            -
                    VALUE str = rb_funcall2(fieldName,  | 
| 161 | 
            +
                    VALUE str = rb_funcall2(fieldName, id_to_s, 0, NULL);
         | 
| 202 162 | 
             
                    rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
         | 
| 203 163 | 
             
                }
         | 
| 204 164 |  | 
| 205 165 | 
             
                return rbField;
         | 
| 206 166 | 
             
            }
         | 
| 207 167 |  | 
| 208 | 
            -
            static inline MemoryOp*
         | 
| 209 | 
            -
            ptr_get_op(AbstractMemory* ptr, int type)
         | 
| 210 | 
            -
            {
         | 
| 211 | 
            -
                if (ptr == NULL || ptr->ops == NULL) {
         | 
| 212 | 
            -
                    return NULL;
         | 
| 213 | 
            -
                }
         | 
| 214 | 
            -
                switch (type) {
         | 
| 215 | 
            -
                    case NATIVE_INT8:
         | 
| 216 | 
            -
                        return ptr->ops->int8;
         | 
| 217 | 
            -
                    case NATIVE_UINT8:
         | 
| 218 | 
            -
                        return ptr->ops->uint8;
         | 
| 219 | 
            -
                    case NATIVE_INT16:
         | 
| 220 | 
            -
                        return ptr->ops->int16;
         | 
| 221 | 
            -
                    case NATIVE_UINT16:
         | 
| 222 | 
            -
                        return ptr->ops->uint16;
         | 
| 223 | 
            -
                    case NATIVE_INT32:
         | 
| 224 | 
            -
                        return ptr->ops->int32;
         | 
| 225 | 
            -
                    case NATIVE_UINT32:
         | 
| 226 | 
            -
                        return ptr->ops->uint32;
         | 
| 227 | 
            -
                    case NATIVE_INT64:
         | 
| 228 | 
            -
                        return ptr->ops->int64;
         | 
| 229 | 
            -
                    case NATIVE_UINT64:
         | 
| 230 | 
            -
                        return ptr->ops->uint64;
         | 
| 231 | 
            -
                    case NATIVE_FLOAT32:
         | 
| 232 | 
            -
                        return ptr->ops->float32;
         | 
| 233 | 
            -
                    case NATIVE_FLOAT64:
         | 
| 234 | 
            -
                        return ptr->ops->float64;
         | 
| 235 | 
            -
                    case NATIVE_POINTER:
         | 
| 236 | 
            -
                        return ptr->ops->pointer;
         | 
| 237 | 
            -
                    case NATIVE_STRING:
         | 
| 238 | 
            -
                        return ptr->ops->strptr;
         | 
| 239 | 
            -
                    default:
         | 
| 240 | 
            -
                        return NULL;
         | 
| 241 | 
            -
                }
         | 
| 242 | 
            -
            }
         | 
| 243 | 
            -
             | 
| 244 168 | 
             
            static VALUE
         | 
| 245 | 
            -
             | 
| 169 | 
            +
            struct_aref(VALUE self, VALUE fieldName)
         | 
| 246 170 | 
             
            {
         | 
| 247 171 | 
             
                Struct* s;
         | 
| 248 172 | 
             
                VALUE rbField;
         | 
| @@ -253,17 +177,17 @@ struct_get_field(VALUE self, VALUE fieldName) | |
| 253 177 | 
             
                rbField = struct_field(s, fieldName);
         | 
| 254 178 | 
             
                f = (StructField *) DATA_PTR(rbField);
         | 
| 255 179 |  | 
| 256 | 
            -
                op =  | 
| 180 | 
            +
                op = memory_get_op(s->pointer, f->type);
         | 
| 257 181 | 
             
                if (op != NULL) {
         | 
| 258 182 | 
             
                    return (*op->get)(s->pointer, f->offset);
         | 
| 259 183 | 
             
                }
         | 
| 260 184 |  | 
| 261 185 | 
             
                /* call up to the ruby code to fetch the value */
         | 
| 262 | 
            -
                return rb_funcall2(rbField,  | 
| 186 | 
            +
                return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
         | 
| 263 187 | 
             
            }
         | 
| 264 188 |  | 
| 265 189 | 
             
            static VALUE
         | 
| 266 | 
            -
             | 
| 190 | 
            +
            struct_aset(VALUE self, VALUE fieldName, VALUE value)
         | 
| 267 191 | 
             
            {
         | 
| 268 192 | 
             
                Struct* s;
         | 
| 269 193 | 
             
                VALUE rbField;
         | 
| @@ -275,7 +199,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value) | |
| 275 199 | 
             
                rbField = struct_field(s, fieldName);
         | 
| 276 200 | 
             
                f = (StructField *) DATA_PTR(rbField);
         | 
| 277 201 |  | 
| 278 | 
            -
                op =  | 
| 202 | 
            +
                op = memory_get_op(s->pointer, f->type);
         | 
| 279 203 | 
             
                if (op != NULL) {
         | 
| 280 204 | 
             
                    (*op->put)(s->pointer, f->offset, value);
         | 
| 281 205 | 
             
                    return self;
         | 
| @@ -284,7 +208,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value) | |
| 284 208 | 
             
                /* call up to the ruby code to set the value */
         | 
| 285 209 | 
             
                argv[0] = s->rbPointer;
         | 
| 286 210 | 
             
                argv[1] = value;
         | 
| 287 | 
            -
                rb_funcall2(rbField,  | 
| 211 | 
            +
                rb_funcall2(rbField, id_put, 2, argv);
         | 
| 288 212 |  | 
| 289 213 | 
             
                return self;
         | 
| 290 214 | 
             
            }
         | 
| @@ -301,7 +225,7 @@ struct_set_pointer(VALUE self, VALUE pointer) | |
| 301 225 | 
             
                Data_Get_Struct(self, Struct, s);
         | 
| 302 226 | 
             
                s->pointer = MEMORY(pointer);
         | 
| 303 227 | 
             
                s->rbPointer = pointer;
         | 
| 304 | 
            -
                rb_ivar_set(self,  | 
| 228 | 
            +
                rb_ivar_set(self, id_pointer_ivar, pointer);
         | 
| 305 229 |  | 
| 306 230 | 
             
                return self;
         | 
| 307 231 | 
             
            }
         | 
| @@ -322,12 +246,12 @@ struct_set_layout(VALUE self, VALUE layout) | |
| 322 246 | 
             
                Struct* s;
         | 
| 323 247 | 
             
                Data_Get_Struct(self, Struct, s);
         | 
| 324 248 |  | 
| 325 | 
            -
                if (!rb_obj_is_kind_of(layout,  | 
| 249 | 
            +
                if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
         | 
| 326 250 | 
             
                    rb_raise(rb_eArgError, "Invalid Struct layout");
         | 
| 327 251 | 
             
                }
         | 
| 328 252 |  | 
| 329 253 | 
             
                Data_Get_Struct(layout, StructLayout, s->layout);
         | 
| 330 | 
            -
                rb_ivar_set(self,  | 
| 254 | 
            +
                rb_ivar_set(self, id_layout_ivar, layout);
         | 
| 331 255 |  | 
| 332 256 | 
             
                return self;
         | 
| 333 257 | 
             
            }
         | 
| @@ -343,76 +267,451 @@ struct_get_layout(VALUE self) | |
| 343 267 | 
             
            }
         | 
| 344 268 |  | 
| 345 269 | 
             
            static VALUE
         | 
| 346 | 
            -
             | 
| 270 | 
            +
            struct_layout_builder_allocate(VALUE klass)
         | 
| 347 271 | 
             
            {
         | 
| 348 | 
            -
                 | 
| 272 | 
            +
                StructLayoutBuilder* builder;
         | 
| 349 273 | 
             
                VALUE obj;
         | 
| 350 | 
            -
             | 
| 351 | 
            -
                obj = Data_Make_Struct(klass,  | 
| 352 | 
            -
             | 
| 274 | 
            +
             | 
| 275 | 
            +
                obj = Data_Make_Struct(klass, StructLayoutBuilder, struct_layout_builder_mark, struct_layout_builder_free, builder);
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                builder->size = 0;
         | 
| 278 | 
            +
                builder->alignment = 1;
         | 
| 279 | 
            +
                builder->isUnion = false;
         | 
| 280 | 
            +
                builder->rbFieldNames = rb_ary_new();
         | 
| 281 | 
            +
                builder->rbFieldMap = rb_hash_new();
         | 
| 353 282 |  | 
| 354 283 | 
             
                return obj;
         | 
| 355 284 | 
             
            }
         | 
| 356 285 |  | 
| 286 | 
            +
            static void
         | 
| 287 | 
            +
            struct_layout_builder_mark(StructLayoutBuilder* builder)
         | 
| 288 | 
            +
            {
         | 
| 289 | 
            +
                rb_gc_mark(builder->rbFieldNames);
         | 
| 290 | 
            +
                rb_gc_mark(builder->rbFieldMap);
         | 
| 291 | 
            +
            }
         | 
| 292 | 
            +
             | 
| 293 | 
            +
            static void
         | 
| 294 | 
            +
            struct_layout_builder_free(StructLayoutBuilder* builder)
         | 
| 295 | 
            +
            {
         | 
| 296 | 
            +
                xfree(builder);
         | 
| 297 | 
            +
            }
         | 
| 298 | 
            +
             | 
| 357 299 | 
             
            static VALUE
         | 
| 358 | 
            -
             | 
| 300 | 
            +
            struct_layout_builder_initialize(VALUE self)
         | 
| 359 301 | 
             
            {
         | 
| 360 | 
            -
                 | 
| 361 | 
            -
             | 
| 302 | 
            +
                StructLayoutBuilder* builder;
         | 
| 303 | 
            +
             | 
| 304 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                return self;
         | 
| 307 | 
            +
            }
         | 
| 308 | 
            +
             | 
| 309 | 
            +
            static VALUE
         | 
| 310 | 
            +
            struct_layout_builder_get_size(VALUE self)
         | 
| 311 | 
            +
            {
         | 
| 312 | 
            +
                StructLayoutBuilder* builder;
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                return UINT2NUM(builder->size);
         | 
| 317 | 
            +
            }
         | 
| 318 | 
            +
             | 
| 319 | 
            +
            static VALUE
         | 
| 320 | 
            +
            struct_layout_builder_set_size(VALUE self, VALUE rbSize)
         | 
| 321 | 
            +
            {
         | 
| 322 | 
            +
                StructLayoutBuilder* builder;
         | 
| 323 | 
            +
                unsigned int size = NUM2UINT(rbSize);
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 326 | 
            +
                builder->size = MAX(size, builder->size);
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                return UINT2NUM(builder->size);
         | 
| 329 | 
            +
            }
         | 
| 330 | 
            +
             | 
| 331 | 
            +
            static VALUE
         | 
| 332 | 
            +
            struct_layout_builder_get_alignment(VALUE self)
         | 
| 333 | 
            +
            {
         | 
| 334 | 
            +
                StructLayoutBuilder* builder;
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 337 | 
            +
             | 
| 338 | 
            +
                return UINT2NUM(builder->alignment);
         | 
| 339 | 
            +
            }
         | 
| 340 | 
            +
             | 
| 341 | 
            +
            static VALUE
         | 
| 342 | 
            +
            struct_layout_builder_set_alignment(VALUE self, VALUE rbAlign)
         | 
| 343 | 
            +
            {
         | 
| 344 | 
            +
                StructLayoutBuilder* builder;
         | 
| 345 | 
            +
                unsigned int align = NUM2UINT(rbAlign);
         | 
| 346 | 
            +
             | 
| 347 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 348 | 
            +
                builder->size = MAX(align, builder->alignment);
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                return UINT2NUM(builder->alignment);
         | 
| 351 | 
            +
            }
         | 
| 362 352 |  | 
| 363 | 
            -
             | 
| 364 | 
            -
             | 
| 365 | 
            -
             | 
| 366 | 
            -
                 | 
| 353 | 
            +
            static VALUE
         | 
| 354 | 
            +
            struct_layout_builder_set_union(VALUE self, VALUE rbUnion)
         | 
| 355 | 
            +
            {
         | 
| 356 | 
            +
                StructLayoutBuilder* builder;
         | 
| 357 | 
            +
             | 
| 358 | 
            +
             | 
| 359 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 360 | 
            +
                builder->isUnion = RTEST(rbUnion);
         | 
| 361 | 
            +
             | 
| 362 | 
            +
                return rbUnion;
         | 
| 363 | 
            +
            }
         | 
| 364 | 
            +
             | 
| 365 | 
            +
            static VALUE
         | 
| 366 | 
            +
            struct_layout_builder_union_p(VALUE self)
         | 
| 367 | 
            +
            {
         | 
| 368 | 
            +
                StructLayoutBuilder* builder;
         | 
| 369 | 
            +
             | 
| 370 | 
            +
             | 
| 371 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 372 | 
            +
             | 
| 373 | 
            +
             | 
| 374 | 
            +
                return builder->isUnion ? Qtrue : Qfalse;
         | 
| 375 | 
            +
            }
         | 
| 376 | 
            +
             | 
| 377 | 
            +
            static void
         | 
| 378 | 
            +
            store_field(StructLayoutBuilder* builder, VALUE rbName, VALUE rbField, 
         | 
| 379 | 
            +
                unsigned int offset, unsigned int size, unsigned int alignment)
         | 
| 380 | 
            +
            {
         | 
| 381 | 
            +
                rb_ary_push(builder->rbFieldNames, rbName);
         | 
| 382 | 
            +
                rb_hash_aset(builder->rbFieldMap, rbName, rbField);
         | 
| 383 | 
            +
             | 
| 384 | 
            +
                builder->alignment = MAX(builder->alignment, alignment);
         | 
| 385 | 
            +
             | 
| 386 | 
            +
                if (builder->isUnion) {
         | 
| 387 | 
            +
                    builder->size = MAX(builder->size, size);
         | 
| 388 | 
            +
                } else {
         | 
| 389 | 
            +
                    builder->size = MAX(builder->size, offset + size);
         | 
| 390 | 
            +
                }
         | 
| 391 | 
            +
            }
         | 
| 392 | 
            +
             | 
| 393 | 
            +
            static int
         | 
| 394 | 
            +
            calculate_offset(StructLayoutBuilder* builder, int alignment, VALUE rbOffset)
         | 
| 395 | 
            +
            {
         | 
| 396 | 
            +
                if (rbOffset != Qnil) {
         | 
| 397 | 
            +
                    return NUM2UINT(rbOffset);
         | 
| 398 | 
            +
                } else {
         | 
| 399 | 
            +
                    return builder->isUnion ? 0 : align(builder->size, alignment);
         | 
| 400 | 
            +
                }
         | 
| 401 | 
            +
            }
         | 
| 402 | 
            +
             | 
| 403 | 
            +
            static VALUE
         | 
| 404 | 
            +
            struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
         | 
| 405 | 
            +
            {
         | 
| 406 | 
            +
                StructLayoutBuilder* builder;
         | 
| 407 | 
            +
                VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
         | 
| 408 | 
            +
                unsigned int size, alignment, offset;
         | 
| 409 | 
            +
                int nargs;
         | 
| 410 | 
            +
             | 
| 411 | 
            +
                nargs = rb_scan_args(argc, argv, "21", &rbName, &rbType, &rbOffset);
         | 
| 367 412 |  | 
| 368 | 
            -
                 | 
| 369 | 
            -
             | 
| 370 | 
            -
                 | 
| 371 | 
            -
                 | 
| 372 | 
            -
             | 
| 373 | 
            -
                 | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 413 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
         | 
| 416 | 
            +
                size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
         | 
| 417 | 
            +
             | 
| 418 | 
            +
                offset = calculate_offset(builder, alignment, rbOffset);
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                //
         | 
| 421 | 
            +
                // If a primitive type was passed in as the type arg, try and convert
         | 
| 422 | 
            +
                //
         | 
| 423 | 
            +
                if (!rb_obj_is_kind_of(rbType, rbffi_StructLayoutFieldClass)) {
         | 
| 424 | 
            +
                    VALUE fargv[3], rbFieldClass;
         | 
| 425 | 
            +
                    fargv[0] = rbName;
         | 
| 426 | 
            +
                    fargv[1] = UINT2NUM(offset);
         | 
| 427 | 
            +
                    fargv[2] = rbType;
         | 
| 428 | 
            +
                    if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
         | 
| 429 | 
            +
                        rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
         | 
| 430 | 
            +
                    } else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
         | 
| 431 | 
            +
                        rbFieldClass = rbffi_StructLayoutStructFieldClass;
         | 
| 432 | 
            +
                    } else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
         | 
| 433 | 
            +
                        rbFieldClass = rbffi_StructLayoutArrayFieldClass;
         | 
| 434 | 
            +
                    } else {
         | 
| 435 | 
            +
                        rbFieldClass = rbffi_StructLayoutFieldClass;
         | 
| 378 436 | 
             
                    }
         | 
| 379 | 
            -
             | 
| 437 | 
            +
             | 
| 438 | 
            +
                    rbField = rb_class_new_instance(3, fargv, rbFieldClass);
         | 
| 439 | 
            +
                } else {
         | 
| 440 | 
            +
                    rbField = rbType;
         | 
| 441 | 
            +
                }
         | 
| 442 | 
            +
             | 
| 443 | 
            +
                store_field(builder, rbName, rbField, offset, size, alignment);
         | 
| 444 | 
            +
                
         | 
| 445 | 
            +
                return self;
         | 
| 446 | 
            +
            }
         | 
| 447 | 
            +
             | 
| 448 | 
            +
            static VALUE
         | 
| 449 | 
            +
            struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
         | 
| 450 | 
            +
            {
         | 
| 451 | 
            +
                StructLayoutBuilder* builder;
         | 
| 452 | 
            +
                VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil, rbStructClass = Qnil;
         | 
| 453 | 
            +
                VALUE fargv[3];
         | 
| 454 | 
            +
                unsigned int size, alignment, offset;
         | 
| 455 | 
            +
                int nargs;
         | 
| 456 | 
            +
             | 
| 457 | 
            +
                nargs = rb_scan_args(argc, argv, "21", &rbName, &rbStructClass, &rbOffset);
         | 
| 458 | 
            +
             | 
| 459 | 
            +
                if (!rb_obj_is_instance_of(rbStructClass, rb_cClass) || !rb_class_inherited(rbStructClass, rbffi_StructClass)) {
         | 
| 460 | 
            +
                    rb_raise(rb_eTypeError, "wrong argument type.  Expected subclass of FFI::Struct");
         | 
| 380 461 | 
             
                }
         | 
| 462 | 
            +
             | 
| 463 | 
            +
                rbType = rb_class_new_instance(1, &rbStructClass, rbffi_StructByValueClass);
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
         | 
| 466 | 
            +
                size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
         | 
| 467 | 
            +
             | 
| 468 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 469 | 
            +
             | 
| 470 | 
            +
                offset = calculate_offset(builder, alignment, rbOffset);
         | 
| 471 | 
            +
             | 
| 472 | 
            +
                fargv[0] = rbName;
         | 
| 473 | 
            +
                fargv[1] = UINT2NUM(offset);
         | 
| 474 | 
            +
                fargv[2] = rbType;
         | 
| 475 | 
            +
                rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutStructFieldClass);
         | 
| 476 | 
            +
                store_field(builder, rbName, rbField, offset, size, alignment);
         | 
| 477 | 
            +
             | 
| 381 478 | 
             
                return self;
         | 
| 382 479 | 
             
            }
         | 
| 383 480 |  | 
| 384 481 | 
             
            static VALUE
         | 
| 385 | 
            -
             | 
| 482 | 
            +
            struct_layout_builder_add_array(int argc, VALUE* argv, VALUE self)
         | 
| 386 483 | 
             
            {
         | 
| 387 | 
            -
                 | 
| 484 | 
            +
                StructLayoutBuilder* builder;
         | 
| 485 | 
            +
                VALUE rbName = Qnil, rbType = Qnil, rbLength = Qnil, rbOffset = Qnil, rbField;
         | 
| 486 | 
            +
                VALUE fargv[3], aargv[2];
         | 
| 487 | 
            +
                unsigned int size, alignment, offset;
         | 
| 488 | 
            +
                int nargs;
         | 
| 489 | 
            +
             | 
| 490 | 
            +
                nargs = rb_scan_args(argc, argv, "31", &rbName, &rbType, &rbLength, &rbOffset);
         | 
| 491 | 
            +
             | 
| 492 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 493 | 
            +
             | 
| 494 | 
            +
                alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
         | 
| 495 | 
            +
                size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL)) * NUM2UINT(rbLength);
         | 
| 388 496 |  | 
| 389 | 
            -
                 | 
| 497 | 
            +
                offset = calculate_offset(builder, alignment, rbOffset);
         | 
| 390 498 |  | 
| 391 | 
            -
                 | 
| 499 | 
            +
                aargv[0] = rbType;
         | 
| 500 | 
            +
                aargv[1] = rbLength;
         | 
| 501 | 
            +
                fargv[0] = rbName;
         | 
| 502 | 
            +
                fargv[1] = UINT2NUM(offset);
         | 
| 503 | 
            +
                fargv[2] = rb_class_new_instance(2, aargv, rbffi_ArrayTypeClass);
         | 
| 504 | 
            +
                rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutArrayFieldClass);
         | 
| 505 | 
            +
             | 
| 506 | 
            +
                store_field(builder, rbName, rbField, offset, size, alignment);
         | 
| 507 | 
            +
             | 
| 508 | 
            +
                return self;
         | 
| 509 | 
            +
            }
         | 
| 510 | 
            +
             | 
| 511 | 
            +
            static inline int
         | 
| 512 | 
            +
            align(int offset, int align)
         | 
| 513 | 
            +
            {
         | 
| 514 | 
            +
                return align + ((offset - 1) & ~(align - 1));
         | 
| 392 515 | 
             
            }
         | 
| 393 516 |  | 
| 517 | 
            +
            static VALUE
         | 
| 518 | 
            +
            struct_layout_builder_build(VALUE self)
         | 
| 519 | 
            +
            {
         | 
| 520 | 
            +
                StructLayoutBuilder* builder;
         | 
| 521 | 
            +
                VALUE argv[4];
         | 
| 522 | 
            +
             | 
| 523 | 
            +
                Data_Get_Struct(self, StructLayoutBuilder, builder);
         | 
| 524 | 
            +
             | 
| 525 | 
            +
                argv[0] = builder->rbFieldNames;
         | 
| 526 | 
            +
                argv[1] = builder->rbFieldMap;
         | 
| 527 | 
            +
                argv[2] = UINT2NUM(align(builder->size, builder->alignment)); // tail padding
         | 
| 528 | 
            +
                argv[3] = UINT2NUM(builder->alignment);
         | 
| 529 | 
            +
             | 
| 530 | 
            +
                return rb_class_new_instance(4, argv, rbffi_StructLayoutClass);
         | 
| 531 | 
            +
            }
         | 
| 532 | 
            +
             | 
| 533 | 
            +
            static VALUE
         | 
| 534 | 
            +
            inline_array_allocate(VALUE klass)
         | 
| 535 | 
            +
            {
         | 
| 536 | 
            +
                InlineArray* array;
         | 
| 537 | 
            +
                VALUE obj;
         | 
| 538 | 
            +
             | 
| 539 | 
            +
                obj = Data_Make_Struct(klass, InlineArray, inline_array_mark, -1, array);
         | 
| 540 | 
            +
                array->rbField = Qnil;
         | 
| 541 | 
            +
                array->rbMemory = Qnil;
         | 
| 542 | 
            +
             | 
| 543 | 
            +
                return obj;
         | 
| 544 | 
            +
            }
         | 
| 394 545 |  | 
| 395 546 | 
             
            static void
         | 
| 396 | 
            -
             | 
| 547 | 
            +
            inline_array_mark(InlineArray* array)
         | 
| 548 | 
            +
            {
         | 
| 549 | 
            +
                rb_gc_mark(array->rbField);
         | 
| 550 | 
            +
                rb_gc_mark(array->rbMemory);
         | 
| 551 | 
            +
            }
         | 
| 552 | 
            +
             | 
| 553 | 
            +
            static VALUE
         | 
| 554 | 
            +
            inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
         | 
| 555 | 
            +
            {
         | 
| 556 | 
            +
                InlineArray* array;
         | 
| 557 | 
            +
                ArrayType* arrayType;
         | 
| 558 | 
            +
             | 
| 559 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 560 | 
            +
                array->rbMemory = rbMemory;
         | 
| 561 | 
            +
                array->rbField = rbField;
         | 
| 562 | 
            +
             | 
| 563 | 
            +
                Data_Get_Struct(rbMemory, AbstractMemory, array->memory);
         | 
| 564 | 
            +
                Data_Get_Struct(rbField, StructField, array->field);
         | 
| 565 | 
            +
                Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
         | 
| 566 | 
            +
                Data_Get_Struct(arrayType->rbComponentType, Type, array->componentType);
         | 
| 567 | 
            +
                
         | 
| 568 | 
            +
                array->op = memory_get_op(array->memory, array->componentType);
         | 
| 569 | 
            +
                if (array->op == NULL) {
         | 
| 570 | 
            +
                    rb_raise(rb_eRuntimeError, "invalid memory ops");
         | 
| 571 | 
            +
                }
         | 
| 572 | 
            +
             | 
| 573 | 
            +
                return self;
         | 
| 574 | 
            +
            }
         | 
| 575 | 
            +
             | 
| 576 | 
            +
            static VALUE
         | 
| 577 | 
            +
            inline_array_size(VALUE self)
         | 
| 578 | 
            +
            {
         | 
| 579 | 
            +
                InlineArray* array;
         | 
| 580 | 
            +
             | 
| 581 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 582 | 
            +
             | 
| 583 | 
            +
                return UINT2NUM(array->field->type->ffiType->size);
         | 
| 584 | 
            +
            }
         | 
| 585 | 
            +
             | 
| 586 | 
            +
            static int
         | 
| 587 | 
            +
            inline_array_offset(InlineArray* array, unsigned int index)
         | 
| 397 588 | 
             
            {
         | 
| 398 | 
            -
                 | 
| 589 | 
            +
                return array->field->offset + (index * array->componentType->ffiType->size);
         | 
| 399 590 | 
             
            }
         | 
| 400 591 |  | 
| 592 | 
            +
            static VALUE
         | 
| 593 | 
            +
            inline_array_aref(VALUE self, VALUE rbIndex)
         | 
| 594 | 
            +
            {
         | 
| 595 | 
            +
                InlineArray* array;
         | 
| 596 | 
            +
             | 
| 597 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 598 | 
            +
             | 
| 599 | 
            +
                return array->op->get(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)));
         | 
| 600 | 
            +
            }
         | 
| 601 | 
            +
             | 
| 602 | 
            +
            static VALUE
         | 
| 603 | 
            +
            inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
         | 
| 604 | 
            +
            {
         | 
| 605 | 
            +
                InlineArray* array;
         | 
| 606 | 
            +
             | 
| 607 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 608 | 
            +
             | 
| 609 | 
            +
                array->op->put(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)),
         | 
| 610 | 
            +
                    rbValue);
         | 
| 611 | 
            +
             | 
| 612 | 
            +
                return rbValue;
         | 
| 613 | 
            +
            }
         | 
| 614 | 
            +
             | 
| 615 | 
            +
            static VALUE
         | 
| 616 | 
            +
            inline_array_each(VALUE self)
         | 
| 617 | 
            +
            {
         | 
| 618 | 
            +
                InlineArray* array;
         | 
| 619 | 
            +
                ArrayType* arrayType;
         | 
| 620 | 
            +
                
         | 
| 621 | 
            +
                int i;
         | 
| 622 | 
            +
             | 
| 623 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 624 | 
            +
                Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
         | 
| 625 | 
            +
             | 
| 626 | 
            +
                for (i = 0; i < arrayType->length; ++i) {
         | 
| 627 | 
            +
                int offset = inline_array_offset(array, i);
         | 
| 628 | 
            +
                    rb_yield(array->op->get(array->memory, offset));
         | 
| 629 | 
            +
                }
         | 
| 630 | 
            +
             | 
| 631 | 
            +
                return self;
         | 
| 632 | 
            +
            }
         | 
| 633 | 
            +
             | 
| 634 | 
            +
            static VALUE
         | 
| 635 | 
            +
            inline_array_to_a(VALUE self)
         | 
| 636 | 
            +
            {
         | 
| 637 | 
            +
                InlineArray* array;
         | 
| 638 | 
            +
                ArrayType* arrayType;
         | 
| 639 | 
            +
                VALUE obj;
         | 
| 640 | 
            +
                int i;
         | 
| 641 | 
            +
             | 
| 642 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 643 | 
            +
                Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
         | 
| 644 | 
            +
                obj = rb_ary_new2(arrayType->length);
         | 
| 645 | 
            +
             | 
| 646 | 
            +
                
         | 
| 647 | 
            +
                for (i = 0; i < arrayType->length; ++i) {
         | 
| 648 | 
            +
                    int offset = inline_array_offset(array, i);
         | 
| 649 | 
            +
                    rb_ary_push(obj, array->op->get(array->memory, offset));
         | 
| 650 | 
            +
                }
         | 
| 651 | 
            +
             | 
| 652 | 
            +
                return obj;
         | 
| 653 | 
            +
            }
         | 
| 654 | 
            +
             | 
| 655 | 
            +
            static VALUE
         | 
| 656 | 
            +
            inline_array_to_s(VALUE self)
         | 
| 657 | 
            +
            {
         | 
| 658 | 
            +
                InlineArray* array;
         | 
| 659 | 
            +
                ArrayType* arrayType;
         | 
| 660 | 
            +
                VALUE argv[2];
         | 
| 661 | 
            +
             | 
| 662 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 663 | 
            +
                Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
         | 
| 664 | 
            +
             | 
| 665 | 
            +
                if (arrayType->componentType->nativeType != NATIVE_INT8 && arrayType->componentType->nativeType != NATIVE_UINT8) {
         | 
| 666 | 
            +
                    rb_raise(rb_eNoMethodError, "to_s not defined for this array type");
         | 
| 667 | 
            +
                    return Qnil;
         | 
| 668 | 
            +
                }
         | 
| 669 | 
            +
             | 
| 670 | 
            +
                argv[0] = UINT2NUM(array->field->offset);
         | 
| 671 | 
            +
                argv[1] = UINT2NUM(arrayType->length);
         | 
| 672 | 
            +
             | 
| 673 | 
            +
                return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
         | 
| 674 | 
            +
            }
         | 
| 675 | 
            +
             | 
| 676 | 
            +
             | 
| 677 | 
            +
            static VALUE
         | 
| 678 | 
            +
            inline_array_to_ptr(VALUE self)
         | 
| 679 | 
            +
            {
         | 
| 680 | 
            +
                InlineArray* array;
         | 
| 681 | 
            +
                AbstractMemory* ptr;
         | 
| 682 | 
            +
                VALUE rbOffset, rbPointer;
         | 
| 683 | 
            +
             | 
| 684 | 
            +
                Data_Get_Struct(self, InlineArray, array);
         | 
| 685 | 
            +
             | 
| 686 | 
            +
                rbOffset = UINT2NUM(array->field->offset);
         | 
| 687 | 
            +
                rbPointer = rb_funcall2(array->rbMemory, rb_intern("+"), 1, &rbOffset);
         | 
| 688 | 
            +
                Data_Get_Struct(rbPointer, AbstractMemory, ptr);
         | 
| 689 | 
            +
                
         | 
| 690 | 
            +
                // Restrict the size of the pointer so ops like ptr.get_string(0) are bounds checked
         | 
| 691 | 
            +
                ptr->size = MIN(ptr->size, array->field->type->ffiType->size);
         | 
| 692 | 
            +
             | 
| 693 | 
            +
                return rbPointer;
         | 
| 694 | 
            +
            }
         | 
| 695 | 
            +
             | 
| 696 | 
            +
             | 
| 401 697 | 
             
            void
         | 
| 402 698 | 
             
            rbffi_Struct_Init(VALUE moduleFFI)
         | 
| 403 699 | 
             
            {
         | 
| 404 | 
            -
                VALUE  | 
| 700 | 
            +
                VALUE StructClass;
         | 
| 701 | 
            +
             | 
| 702 | 
            +
                rbffi_StructLayout_Init(moduleFFI);
         | 
| 703 | 
            +
             | 
| 405 704 | 
             
                rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
         | 
| 406 705 | 
             
                rb_global_variable(&rbffi_StructClass);
         | 
| 407 706 |  | 
| 408 | 
            -
                StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rb_cObject);
         | 
| 409 | 
            -
                rb_global_variable(&StructLayoutClass);
         | 
| 410 707 |  | 
| 411 708 | 
             
                StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
         | 
| 412 709 | 
             
                rb_global_variable(&StructLayoutBuilderClass);
         | 
| 413 710 |  | 
| 414 | 
            -
                 | 
| 415 | 
            -
                rb_global_variable(& | 
| 711 | 
            +
                rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
         | 
| 712 | 
            +
                rb_global_variable(&rbffi_StructInlineArrayClass);
         | 
| 713 | 
            +
             | 
| 714 | 
            +
             | 
| 416 715 |  | 
| 417 716 | 
             
                rb_define_alloc_func(StructClass, struct_allocate);
         | 
| 418 717 | 
             
                rb_define_method(StructClass, "initialize", struct_initialize, -1);
         | 
| @@ -430,48 +729,42 @@ rbffi_Struct_Init(VALUE moduleFFI) | |
| 430 729 | 
             
                rb_define_method(StructClass, "layout", struct_get_layout, 0);
         | 
| 431 730 | 
             
                rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
         | 
| 432 731 |  | 
| 433 | 
            -
                rb_define_method(StructClass, "[]",  | 
| 434 | 
            -
                rb_define_method(StructClass, "[]=",  | 
| 732 | 
            +
                rb_define_method(StructClass, "[]", struct_aref, 1);
         | 
| 733 | 
            +
                rb_define_method(StructClass, "[]=", struct_aset, 2);
         | 
| 435 734 |  | 
| 436 | 
            -
                rb_define_alloc_func(StructFieldClass, struct_field_allocate);
         | 
| 437 | 
            -
                rb_define_method(StructFieldClass, "initialize", struct_field_initialize, -1);
         | 
| 438 | 
            -
                rb_define_method(StructFieldClass, "offset", struct_field_offset, 0);
         | 
| 439 | 
            -
                rb_define_method(StructFieldClass, "put", struct_field_put, 2);
         | 
| 440 | 
            -
                rb_define_method(StructFieldClass, "get", struct_field_get, 1);
         | 
| 441 | 
            -
             | 
| 442 | 
            -
                rb_define_alloc_func(StructLayoutClass, struct_layout_allocate);
         | 
| 443 | 
            -
                rb_define_method(StructLayoutClass, "initialize", struct_layout_initialize, 4);
         | 
| 444 | 
            -
                rb_define_method(StructLayoutClass, "[]", struct_layout_aref, 1);
         | 
| 445 | 
            -
             | 
| 446 | 
            -
                pointer_var_id = rb_intern("@pointer");
         | 
| 447 | 
            -
                layout_var_id = rb_intern("@layout");
         | 
| 448 | 
            -
                layout_id = rb_intern("layout");
         | 
| 449 | 
            -
                get_id = rb_intern("get");
         | 
| 450 | 
            -
                put_id = rb_intern("put");
         | 
| 451 | 
            -
                to_ptr = rb_intern("to_ptr");
         | 
| 452 | 
            -
                to_s = rb_intern("to_s");
         | 
| 453 | 
            -
                SIZE_ID = rb_intern("SIZE");
         | 
| 454 | 
            -
                ALIGN_ID = rb_intern("ALIGN");
         | 
| 455 | 
            -
                TYPE_ID = rb_intern("TYPE");
         | 
| 456 | 
            -
            #undef FIELD
         | 
| 457 | 
            -
            #define FIELD(name, typeName, nativeType, T) do { \
         | 
| 458 | 
            -
                typedef struct { char c; T v; } s; \
         | 
| 459 | 
            -
                    klass = rb_define_class_under(StructLayoutBuilderClass, #name, StructFieldClass); \
         | 
| 460 | 
            -
                    rb_define_const(klass, "ALIGN", INT2NUM((sizeof(s) - sizeof(T)))); \
         | 
| 461 | 
            -
                    rb_define_const(klass, "SIZE", INT2NUM(sizeof(T))); \
         | 
| 462 | 
            -
                    rb_define_const(klass, "TYPE", INT2NUM(nativeType)); \
         | 
| 463 | 
            -
                } while(0)
         | 
| 464 735 |  | 
| 465 | 
            -
             | 
| 466 | 
            -
                 | 
| 467 | 
            -
                 | 
| 468 | 
            -
                 | 
| 469 | 
            -
             | 
| 470 | 
            -
                 | 
| 471 | 
            -
                 | 
| 472 | 
            -
                 | 
| 473 | 
            -
                 | 
| 474 | 
            -
                 | 
| 475 | 
            -
                 | 
| 476 | 
            -
                 | 
| 736 | 
            +
             | 
| 737 | 
            +
                rb_define_alloc_func(StructLayoutBuilderClass, struct_layout_builder_allocate);
         | 
| 738 | 
            +
                rb_define_method(StructLayoutBuilderClass, "initialize", struct_layout_builder_initialize, 0);
         | 
| 739 | 
            +
                rb_define_method(StructLayoutBuilderClass, "build", struct_layout_builder_build, 0);
         | 
| 740 | 
            +
             | 
| 741 | 
            +
                rb_define_method(StructLayoutBuilderClass, "alignment", struct_layout_builder_get_alignment, 0);
         | 
| 742 | 
            +
                rb_define_method(StructLayoutBuilderClass, "alignment=", struct_layout_builder_set_alignment, 1);
         | 
| 743 | 
            +
                rb_define_method(StructLayoutBuilderClass, "size", struct_layout_builder_get_size, 0);
         | 
| 744 | 
            +
                rb_define_method(StructLayoutBuilderClass, "size=", struct_layout_builder_set_size, 1);
         | 
| 745 | 
            +
                rb_define_method(StructLayoutBuilderClass, "union=", struct_layout_builder_set_union, 1);
         | 
| 746 | 
            +
                rb_define_method(StructLayoutBuilderClass, "union?", struct_layout_builder_union_p, 0);
         | 
| 747 | 
            +
                rb_define_method(StructLayoutBuilderClass, "add_field", struct_layout_builder_add_field, -1);
         | 
| 748 | 
            +
                rb_define_method(StructLayoutBuilderClass, "add_array", struct_layout_builder_add_array, -1);
         | 
| 749 | 
            +
                rb_define_method(StructLayoutBuilderClass, "add_struct", struct_layout_builder_add_struct, -1);
         | 
| 750 | 
            +
             | 
| 751 | 
            +
                rb_include_module(rbffi_StructInlineArrayClass, rb_mEnumerable);
         | 
| 752 | 
            +
                rb_define_alloc_func(rbffi_StructInlineArrayClass, inline_array_allocate);
         | 
| 753 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "initialize", inline_array_initialize, 2);
         | 
| 754 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "[]", inline_array_aref, 1);
         | 
| 755 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "[]=", inline_array_aset, 2);
         | 
| 756 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "each", inline_array_each, 0);
         | 
| 757 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "size", inline_array_size, 0);
         | 
| 758 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "to_a", inline_array_to_a, 0);
         | 
| 759 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "to_s", inline_array_to_s, 0);
         | 
| 760 | 
            +
                rb_define_alias(rbffi_StructInlineArrayClass, "to_str", "to_s");
         | 
| 761 | 
            +
                rb_define_method(rbffi_StructInlineArrayClass, "to_ptr", inline_array_to_ptr, 0);
         | 
| 762 | 
            +
             | 
| 763 | 
            +
                id_pointer_ivar = rb_intern("@pointer");
         | 
| 764 | 
            +
                id_layout_ivar = rb_intern("@layout");
         | 
| 765 | 
            +
                id_layout = rb_intern("layout");
         | 
| 766 | 
            +
                id_get = rb_intern("get");
         | 
| 767 | 
            +
                id_put = rb_intern("put");
         | 
| 768 | 
            +
                id_to_ptr = rb_intern("to_ptr");
         | 
| 769 | 
            +
                id_to_s = rb_intern("to_s");
         | 
| 477 770 | 
             
            }
         |