ffi 0.3.5 → 0.4.0
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 +51 -1
 - data/Rakefile +34 -26
 - data/ext/ffi_c/AbstractMemory.c +73 -70
 - data/ext/ffi_c/AbstractMemory.h +8 -4
 - data/ext/ffi_c/AutoPointer.c +8 -9
 - data/ext/ffi_c/AutoPointer.h +2 -2
 - data/ext/ffi_c/Buffer.c +19 -20
 - data/ext/ffi_c/Callback.c +85 -33
 - data/ext/ffi_c/Callback.h +11 -5
 - data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +83 -16
 - data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
 - data/ext/ffi_c/Invoker.c +148 -192
 - data/ext/ffi_c/LastError.c +135 -0
 - data/ext/ffi_c/LastError.h +18 -0
 - data/ext/ffi_c/MemoryPointer.c +26 -19
 - data/ext/ffi_c/MemoryPointer.h +3 -3
 - data/ext/ffi_c/NullPointer.c +49 -47
 - data/ext/ffi_c/Platform.c +9 -10
 - data/ext/ffi_c/Platform.h +1 -1
 - data/ext/ffi_c/Pointer.c +52 -21
 - data/ext/ffi_c/Pointer.h +8 -6
 - data/ext/ffi_c/Struct.c +70 -61
 - data/ext/ffi_c/Struct.h +2 -2
 - data/ext/ffi_c/Type.c +230 -0
 - data/ext/ffi_c/Type.h +28 -0
 - data/ext/ffi_c/Types.c +47 -6
 - data/ext/ffi_c/Types.h +8 -2
 - data/ext/ffi_c/endian.h +40 -0
 - data/ext/ffi_c/extconf.rb +6 -5
 - data/ext/ffi_c/ffi.c +20 -43
 - data/ext/ffi_c/libffi.bsd.mk +34 -0
 - data/ext/ffi_c/libffi.darwin.mk +30 -10
 - data/ext/ffi_c/libffi.gnu.mk +29 -0
 - data/ext/ffi_c/libffi.mk +4 -2
 - data/ext/ffi_c/rbffi.h +6 -8
 - data/lib/ffi.rb +10 -1
 - data/lib/ffi/autopointer.rb +1 -1
 - data/lib/ffi/enum.rb +78 -0
 - data/lib/ffi/ffi.rb +5 -6
 - data/lib/ffi/io.rb +15 -1
 - data/lib/ffi/library.rb +78 -17
 - data/lib/ffi/pointer.rb +2 -2
 - data/lib/ffi/struct.rb +68 -14
 - data/lib/ffi/types.rb +6 -3
 - data/lib/ffi/variadic.rb +2 -2
 - data/spec/ffi/bool_spec.rb +24 -0
 - data/spec/ffi/callback_spec.rb +217 -17
 - data/spec/ffi/enum_spec.rb +164 -0
 - data/spec/ffi/managed_struct_spec.rb +6 -1
 - data/spec/ffi/number_spec.rb +30 -0
 - data/spec/ffi/pointer_spec.rb +33 -8
 - data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
 - data/spec/ffi/spec_helper.rb +5 -1
 - data/spec/ffi/string_spec.rb +65 -4
 - data/spec/ffi/struct_callback_spec.rb +41 -0
 - data/spec/ffi/struct_initialize_spec.rb +30 -0
 - data/spec/ffi/struct_spec.rb +19 -20
 - metadata +29 -52
 - data/ext/ffi_c/ffi.mk +0 -23
 
    
        data/ext/ffi_c/Pointer.c
    CHANGED
    
    | 
         @@ -11,26 +11,25 @@ typedef struct Pointer { 
     | 
|
| 
       11 
11 
     | 
    
         
             
                VALUE parent;
         
     | 
| 
       12 
12 
     | 
    
         
             
            } Pointer;
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
            #define POINTER(obj)  
     | 
| 
      
 14 
     | 
    
         
            +
            #define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass)
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
            VALUE  
     | 
| 
       17 
     | 
    
         
            -
            static VALUE classPointer = Qnil;
         
     | 
| 
      
 16 
     | 
    
         
            +
            VALUE rbffi_PointerClass;
         
     | 
| 
       18 
17 
     | 
    
         
             
            static void ptr_mark(Pointer* ptr);
         
     | 
| 
       19 
18 
     | 
    
         | 
| 
       20 
19 
     | 
    
         
             
            VALUE
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
            rbffi_Pointer_NewInstance(void* addr)
         
     | 
| 
       22 
21 
     | 
    
         
             
            {
         
     | 
| 
       23 
22 
     | 
    
         
             
                Pointer* p;
         
     | 
| 
       24 
23 
     | 
    
         
             
                VALUE obj;
         
     | 
| 
       25 
24 
     | 
    
         | 
| 
       26 
25 
     | 
    
         
             
                if (addr == NULL) {
         
     | 
| 
       27 
     | 
    
         
            -
                    return  
     | 
| 
      
 26 
     | 
    
         
            +
                    return rbffi_NullPointerSingleton;
         
     | 
| 
       28 
27 
     | 
    
         
             
                }
         
     | 
| 
       29 
28 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                obj = Data_Make_Struct( 
     | 
| 
      
 29 
     | 
    
         
            +
                obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
         
     | 
| 
       31 
30 
     | 
    
         
             
                p->memory.address = addr;
         
     | 
| 
       32 
31 
     | 
    
         
             
                p->memory.size = LONG_MAX;
         
     | 
| 
       33 
     | 
    
         
            -
                p->memory.ops = & 
     | 
| 
      
 32 
     | 
    
         
            +
                p->memory.ops = &rbffi_AbstractMemoryOps;
         
     | 
| 
       34 
33 
     | 
    
         
             
                p->parent = Qnil;
         
     | 
| 
       35 
34 
     | 
    
         | 
| 
       36 
35 
     | 
    
         
             
                return obj;
         
     | 
| 
         @@ -42,12 +41,43 @@ ptr_allocate(VALUE klass) 
     | 
|
| 
       42 
41 
     | 
    
         
             
                Pointer* p;
         
     | 
| 
       43 
42 
     | 
    
         
             
                VALUE obj;
         
     | 
| 
       44 
43 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                obj = Data_Make_Struct( 
     | 
| 
      
 44 
     | 
    
         
            +
                obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
         
     | 
| 
       46 
45 
     | 
    
         
             
                p->parent = Qnil;
         
     | 
| 
      
 46 
     | 
    
         
            +
                p->memory.ops = &rbffi_AbstractMemoryOps;
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                return obj;
         
     | 
| 
       49 
49 
     | 
    
         
             
            }
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
      
 51 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 52 
     | 
    
         
            +
            ptr_initialize(int argc, VALUE* argv, VALUE self)
         
     | 
| 
      
 53 
     | 
    
         
            +
            {
         
     | 
| 
      
 54 
     | 
    
         
            +
                Pointer* p;
         
     | 
| 
      
 55 
     | 
    
         
            +
                VALUE type, address;
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                Data_Get_Struct(self, Pointer, p);
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                switch (rb_scan_args(argc, argv, "11", &type, &address)) {
         
     | 
| 
      
 60 
     | 
    
         
            +
                    case 1:
         
     | 
| 
      
 61 
     | 
    
         
            +
                        p->memory.address = (void*)(uintptr_t) NUM2LL(type);
         
     | 
| 
      
 62 
     | 
    
         
            +
                        // FIXME set type_size to 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 64 
     | 
    
         
            +
                    case 2:
         
     | 
| 
      
 65 
     | 
    
         
            +
                        p->memory.address = (void*)(uintptr_t) NUM2LL(address);
         
     | 
| 
      
 66 
     | 
    
         
            +
                        // FIXME set type_size to rbffi_type_size(type)
         
     | 
| 
      
 67 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 68 
     | 
    
         
            +
                    default:
         
     | 
| 
      
 69 
     | 
    
         
            +
                        rb_raise(rb_eArgError, "Invalid arguments");
         
     | 
| 
      
 70 
     | 
    
         
            +
                }
         
     | 
| 
      
 71 
     | 
    
         
            +
                if (p->memory.address == NULL) {
         
     | 
| 
      
 72 
     | 
    
         
            +
                    p->memory.ops = &rbffi_NullPointerOps;
         
     | 
| 
      
 73 
     | 
    
         
            +
                }
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                p->memory.size = LONG_MAX;
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
                return self;
         
     | 
| 
      
 78 
     | 
    
         
            +
            }
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
       51 
81 
     | 
    
         
             
            static VALUE
         
     | 
| 
       52 
82 
     | 
    
         
             
            ptr_plus(VALUE self, VALUE offset)
         
     | 
| 
       53 
83 
     | 
    
         
             
            {
         
     | 
| 
         @@ -59,11 +89,11 @@ ptr_plus(VALUE self, VALUE offset) 
     | 
|
| 
       59 
89 
     | 
    
         
             
                Data_Get_Struct(self, AbstractMemory, ptr);
         
     | 
| 
       60 
90 
     | 
    
         
             
                checkBounds(ptr, off, 1);
         
     | 
| 
       61 
91 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                retval = Data_Make_Struct( 
     | 
| 
      
 92 
     | 
    
         
            +
                retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
         
     | 
| 
       63 
93 
     | 
    
         | 
| 
       64 
94 
     | 
    
         
             
                p->memory.address = ptr->address + off;
         
     | 
| 
       65 
95 
     | 
    
         
             
                p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
         
     | 
| 
       66 
     | 
    
         
            -
                p->memory.ops = & 
     | 
| 
      
 96 
     | 
    
         
            +
                p->memory.ops = &rbffi_AbstractMemoryOps;
         
     | 
| 
       67 
97 
     | 
    
         
             
                p->parent = self;
         
     | 
| 
       68 
98 
     | 
    
         | 
| 
       69 
99 
     | 
    
         
             
                return retval;
         
     | 
| 
         @@ -118,16 +148,17 @@ ptr_mark(Pointer* ptr) 
     | 
|
| 
       118 
148 
     | 
    
         
             
            }
         
     | 
| 
       119 
149 
     | 
    
         | 
| 
       120 
150 
     | 
    
         
             
            void
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
      
 151 
     | 
    
         
            +
            rbffi_Pointer_Init(VALUE moduleFFI)
         
     | 
| 
       122 
152 
     | 
    
         
             
            {
         
     | 
| 
       123 
     | 
    
         
            -
                 
     | 
| 
       124 
     | 
    
         
            -
                 
     | 
| 
       125 
     | 
    
         
            -
             
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
                 
     | 
| 
       128 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       129 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       130 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       131 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       132 
     | 
    
         
            -
                 
     | 
| 
      
 153 
     | 
    
         
            +
                rbffi_PointerClass = rb_define_class_under(moduleFFI, "Pointer", rbffi_AbstractMemoryClass);
         
     | 
| 
      
 154 
     | 
    
         
            +
                rb_global_variable(&rbffi_PointerClass);
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                rb_define_alloc_func(rbffi_PointerClass, ptr_allocate);
         
     | 
| 
      
 157 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "initialize", ptr_initialize, -1);
         
     | 
| 
      
 158 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "inspect", ptr_inspect, 0);
         
     | 
| 
      
 159 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "+", ptr_plus, 1);
         
     | 
| 
      
 160 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "null?", ptr_null_p, 0);
         
     | 
| 
      
 161 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "address", ptr_address, 0);
         
     | 
| 
      
 162 
     | 
    
         
            +
                rb_define_alias(rbffi_PointerClass, "to_i", "address");
         
     | 
| 
      
 163 
     | 
    
         
            +
                rb_define_method(rbffi_PointerClass, "==", ptr_equals, 1);
         
     | 
| 
       133 
164 
     | 
    
         
             
            }
         
     | 
    
        data/ext/ffi_c/Pointer.h
    CHANGED
    
    | 
         @@ -6,14 +6,16 @@ 
     | 
|
| 
       6 
6 
     | 
    
         
             
            extern "C" {
         
     | 
| 
       7 
7 
     | 
    
         
             
            #endif
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
            #include "AbstractMemory.h"
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
            extern void rbffi_Pointer_Init(VALUE moduleFFI);
         
     | 
| 
      
 12 
     | 
    
         
            +
            extern void rbffi_NullPointer_Init(VALUE moduleFFI);
         
     | 
| 
      
 13 
     | 
    
         
            +
            extern VALUE rbffi_Pointer_NewInstance(void* addr);
         
     | 
| 
      
 14 
     | 
    
         
            +
            extern VALUE rbffi_PointerClass;
         
     | 
| 
      
 15 
     | 
    
         
            +
            extern VALUE rbffi_NullPointerClass;
         
     | 
| 
      
 16 
     | 
    
         
            +
            extern VALUE rbffi_NullPointerSingleton;
         
     | 
| 
      
 17 
     | 
    
         
            +
            extern MemoryOps rbffi_NullPointerOps;
         
     | 
| 
       10 
18 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            extern void rb_FFI_Pointer_Init(void);
         
     | 
| 
       12 
     | 
    
         
            -
            extern void rb_FFI_NullPointer_Init(void);
         
     | 
| 
       13 
     | 
    
         
            -
            extern VALUE rb_FFI_Pointer_new(void* addr);
         
     | 
| 
       14 
     | 
    
         
            -
            extern VALUE rb_FFI_Pointer_class;
         
     | 
| 
       15 
     | 
    
         
            -
            extern VALUE rb_FFI_NullPointer_class;
         
     | 
| 
       16 
     | 
    
         
            -
            extern VALUE rb_FFI_NullPointer_singleton;
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
20 
     | 
    
         
             
            #ifdef	__cplusplus
         
     | 
| 
       19 
21 
     | 
    
         
             
            }
         
     | 
    
        data/ext/ffi_c/Struct.c
    CHANGED
    
    | 
         @@ -33,11 +33,11 @@ static void struct_mark(Struct *); 
     | 
|
| 
       33 
33 
     | 
    
         
             
            static void struct_layout_mark(StructLayout *);
         
     | 
| 
       34 
34 
     | 
    
         
             
            static inline MemoryOp* ptr_get_op(AbstractMemory* ptr, int type);
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
            VALUE  
     | 
| 
       37 
     | 
    
         
            -
            static VALUE  
     | 
| 
       38 
     | 
    
         
            -
            static VALUE  
     | 
| 
       39 
     | 
    
         
            -
            static ID  
     | 
| 
       40 
     | 
    
         
            -
            static ID  
     | 
| 
      
 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 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
            static VALUE
         
     | 
| 
       43 
43 
     | 
    
         
             
            struct_field_allocate(VALUE klass)
         
     | 
| 
         @@ -58,15 +58,15 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self) 
     | 
|
| 
       58 
58 
     | 
    
         
             
                nargs = rb_scan_args(argc, argv, "11", &offset, &info);
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
       60 
60 
     | 
    
         
             
                field->offset = NUM2UINT(offset);
         
     | 
| 
       61 
     | 
    
         
            -
                if (rb_const_defined(CLASS_OF(self),  
     | 
| 
       62 
     | 
    
         
            -
                    field->type = NUM2UINT(rb_const_get(CLASS_OF(self),  
     | 
| 
      
 61 
     | 
    
         
            +
                if (rb_const_defined(CLASS_OF(self), TYPE_ID)) {
         
     | 
| 
      
 62 
     | 
    
         
            +
                    field->type = NUM2UINT(rb_const_get(CLASS_OF(self), TYPE_ID));
         
     | 
| 
       63 
63 
     | 
    
         
             
                } else {
         
     | 
| 
       64 
64 
     | 
    
         
             
                    field->type = ~0;
         
     | 
| 
       65 
65 
     | 
    
         
             
                }
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
       67 
67 
     | 
    
         
             
            #ifdef notyet
         
     | 
| 
       68 
     | 
    
         
            -
                field->size = NUM2UINT(rb_const_get(klass,  
     | 
| 
       69 
     | 
    
         
            -
                field->align = NUM2UINT(rb_const_get(klass,  
     | 
| 
      
 68 
     | 
    
         
            +
                field->size = NUM2UINT(rb_const_get(klass, SIZE_ID));
         
     | 
| 
      
 69 
     | 
    
         
            +
                field->align = NUM2UINT(rb_const_get(klass, ALIGN_ID));
         
     | 
| 
       70 
70 
     | 
    
         
             
            #endif
         
     | 
| 
       71 
71 
     | 
    
         
             
                rb_iv_set(self, "@off", offset);
         
     | 
| 
       72 
72 
     | 
    
         
             
                rb_iv_set(self, "@info", info);
         
     | 
| 
         @@ -151,14 +151,14 @@ struct_initialize(int argc, VALUE* argv, VALUE self) 
     | 
|
| 
       151 
151 
     | 
    
         | 
| 
       152 
152 
     | 
    
         
             
                /* Call up into ruby code to adjust the layout */
         
     | 
| 
       153 
153 
     | 
    
         
             
                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,  
     | 
| 
      
 154 
     | 
    
         
            +
                    s->rbLayout = rb_funcall2(CLASS_OF(self), layout_id, RARRAY_LEN(rest), RARRAY_PTR(rest));
         
     | 
| 
      
 155 
     | 
    
         
            +
                } else if (rb_cvar_defined(klass, layout_var_id)) {
         
     | 
| 
      
 156 
     | 
    
         
            +
                    s->rbLayout = rb_cvar_get(klass, layout_var_id);
         
     | 
| 
       157 
157 
     | 
    
         
             
                } else {
         
     | 
| 
       158 
158 
     | 
    
         
             
                    rb_raise(rb_eRuntimeError, "No Struct layout configured");
         
     | 
| 
       159 
159 
     | 
    
         
             
                }
         
     | 
| 
       160 
160 
     | 
    
         | 
| 
       161 
     | 
    
         
            -
                if (!rb_obj_is_kind_of(s->rbLayout,  
     | 
| 
      
 161 
     | 
    
         
            +
                if (!rb_obj_is_kind_of(s->rbLayout, StructLayoutClass)) {
         
     | 
| 
       162 
162 
     | 
    
         
             
                    rb_raise(rb_eRuntimeError, "Invalid Struct layout");
         
     | 
| 
       163 
163 
     | 
    
         
             
                }
         
     | 
| 
       164 
164 
     | 
    
         | 
| 
         @@ -168,7 +168,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self) 
     | 
|
| 
       168 
168 
     | 
    
         
             
                    s->pointer = MEMORY(rbPointer);
         
     | 
| 
       169 
169 
     | 
    
         
             
                    s->rbPointer = rbPointer;
         
     | 
| 
       170 
170 
     | 
    
         
             
                } else {
         
     | 
| 
       171 
     | 
    
         
            -
                    s->rbPointer =  
     | 
| 
      
 171 
     | 
    
         
            +
                    s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
         
     | 
| 
       172 
172 
     | 
    
         
             
                    s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
         
     | 
| 
       173 
173 
     | 
    
         
             
                }
         
     | 
| 
       174 
174 
     | 
    
         | 
| 
         @@ -198,7 +198,7 @@ struct_field(Struct* s, VALUE fieldName) 
     | 
|
| 
       198 
198 
     | 
    
         | 
| 
       199 
199 
     | 
    
         
             
                rbField = rb_hash_aref(layout->rbFields, fieldName);
         
     | 
| 
       200 
200 
     | 
    
         
             
                if (rbField == Qnil) {
         
     | 
| 
       201 
     | 
    
         
            -
                    VALUE str = rb_funcall2(fieldName,  
     | 
| 
      
 201 
     | 
    
         
            +
                    VALUE str = rb_funcall2(fieldName, to_s, 0, NULL);
         
     | 
| 
       202 
202 
     | 
    
         
             
                    rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
         
     | 
| 
       203 
203 
     | 
    
         
             
                }
         
     | 
| 
       204 
204 
     | 
    
         | 
| 
         @@ -259,7 +259,7 @@ struct_get_field(VALUE self, VALUE fieldName) 
     | 
|
| 
       259 
259 
     | 
    
         
             
                }
         
     | 
| 
       260 
260 
     | 
    
         | 
| 
       261 
261 
     | 
    
         
             
                /* call up to the ruby code to fetch the value */
         
     | 
| 
       262 
     | 
    
         
            -
                return rb_funcall2(rbField,  
     | 
| 
      
 262 
     | 
    
         
            +
                return rb_funcall2(rbField, get_id, 1, &s->rbPointer);
         
     | 
| 
       263 
263 
     | 
    
         
             
            }
         
     | 
| 
       264 
264 
     | 
    
         | 
| 
       265 
265 
     | 
    
         
             
            static VALUE
         
     | 
| 
         @@ -284,7 +284,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value) 
     | 
|
| 
       284 
284 
     | 
    
         
             
                /* call up to the ruby code to set the value */
         
     | 
| 
       285 
285 
     | 
    
         
             
                argv[0] = s->rbPointer;
         
     | 
| 
       286 
286 
     | 
    
         
             
                argv[1] = value;
         
     | 
| 
       287 
     | 
    
         
            -
                rb_funcall2(rbField,  
     | 
| 
      
 287 
     | 
    
         
            +
                rb_funcall2(rbField, put_id, 2, argv);
         
     | 
| 
       288 
288 
     | 
    
         | 
| 
       289 
289 
     | 
    
         
             
                return self;
         
     | 
| 
       290 
290 
     | 
    
         
             
            }
         
     | 
| 
         @@ -294,14 +294,14 @@ struct_set_pointer(VALUE self, VALUE pointer) 
     | 
|
| 
       294 
294 
     | 
    
         
             
            {
         
     | 
| 
       295 
295 
     | 
    
         
             
                Struct* s;
         
     | 
| 
       296 
296 
     | 
    
         | 
| 
       297 
     | 
    
         
            -
                if (!rb_obj_is_kind_of(pointer,  
     | 
| 
      
 297 
     | 
    
         
            +
                if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
         
     | 
| 
       298 
298 
     | 
    
         
             
                    rb_raise(rb_eArgError, "Invalid pointer");
         
     | 
| 
       299 
299 
     | 
    
         
             
                }
         
     | 
| 
       300 
300 
     | 
    
         | 
| 
       301 
301 
     | 
    
         
             
                Data_Get_Struct(self, Struct, s);
         
     | 
| 
       302 
302 
     | 
    
         
             
                s->pointer = MEMORY(pointer);
         
     | 
| 
       303 
303 
     | 
    
         
             
                s->rbPointer = pointer;
         
     | 
| 
       304 
     | 
    
         
            -
                rb_ivar_set(self,  
     | 
| 
      
 304 
     | 
    
         
            +
                rb_ivar_set(self, pointer_var_id, pointer);
         
     | 
| 
       305 
305 
     | 
    
         | 
| 
       306 
306 
     | 
    
         
             
                return self;
         
     | 
| 
       307 
307 
     | 
    
         
             
            }
         
     | 
| 
         @@ -322,12 +322,12 @@ struct_set_layout(VALUE self, VALUE layout) 
     | 
|
| 
       322 
322 
     | 
    
         
             
                Struct* s;
         
     | 
| 
       323 
323 
     | 
    
         
             
                Data_Get_Struct(self, Struct, s);
         
     | 
| 
       324 
324 
     | 
    
         | 
| 
       325 
     | 
    
         
            -
                if (!rb_obj_is_kind_of(layout,  
     | 
| 
      
 325 
     | 
    
         
            +
                if (!rb_obj_is_kind_of(layout, StructLayoutClass)) {
         
     | 
| 
       326 
326 
     | 
    
         
             
                    rb_raise(rb_eArgError, "Invalid Struct layout");
         
     | 
| 
       327 
327 
     | 
    
         
             
                }
         
     | 
| 
       328 
328 
     | 
    
         | 
| 
       329 
329 
     | 
    
         
             
                Data_Get_Struct(layout, StructLayout, s->layout);
         
     | 
| 
       330 
     | 
    
         
            -
                rb_ivar_set(self,  
     | 
| 
      
 330 
     | 
    
         
            +
                rb_ivar_set(self, layout_var_id, layout);
         
     | 
| 
       331 
331 
     | 
    
         | 
| 
       332 
332 
     | 
    
         
             
                return self;
         
     | 
| 
       333 
333 
     | 
    
         
             
            }
         
     | 
| 
         @@ -373,7 +373,7 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size 
     | 
|
| 
       373 
373 
     | 
    
         
             
                for (i = 0; i < RARRAY_LEN(field_names); ++i) {
         
     | 
| 
       374 
374 
     | 
    
         
             
                    VALUE name = RARRAY_PTR(field_names)[i];
         
     | 
| 
       375 
375 
     | 
    
         
             
                    VALUE field = rb_hash_aref(fields, name);
         
     | 
| 
       376 
     | 
    
         
            -
                    if (TYPE(field) != T_DATA || !rb_obj_is_kind_of(field,  
     | 
| 
      
 376 
     | 
    
         
            +
                    if (TYPE(field) != T_DATA || !rb_obj_is_kind_of(field, StructFieldClass)) {
         
     | 
| 
       377 
377 
     | 
    
         
             
                        rb_raise(rb_eArgError, "Invalid field");
         
     | 
| 
       378 
378 
     | 
    
         
             
                    }
         
     | 
| 
       379 
379 
     | 
    
         
             
                    rb_hash_aset(layout->rbFields, name, field);
         
     | 
| 
         @@ -399,57 +399,66 @@ struct_layout_mark(StructLayout *layout) 
     | 
|
| 
       399 
399 
     | 
    
         
             
            }
         
     | 
| 
       400 
400 
     | 
    
         | 
| 
       401 
401 
     | 
    
         
             
            void
         
     | 
| 
       402 
     | 
    
         
            -
             
     | 
| 
      
 402 
     | 
    
         
            +
            rbffi_Struct_Init(VALUE moduleFFI)
         
     | 
| 
       403 
403 
     | 
    
         
             
            {
         
     | 
| 
       404 
     | 
    
         
            -
                VALUE  
     | 
| 
       405 
     | 
    
         
            -
                 
     | 
| 
       406 
     | 
    
         
            -
                 
     | 
| 
       407 
     | 
    
         
            -
             
     | 
| 
       408 
     | 
    
         
            -
                 
     | 
| 
       409 
     | 
    
         
            -
                 
     | 
| 
       410 
     | 
    
         
            -
             
     | 
| 
       411 
     | 
    
         
            -
                 
     | 
| 
       412 
     | 
    
         
            -
                 
     | 
| 
      
 404 
     | 
    
         
            +
                VALUE klass, StructClass;
         
     | 
| 
      
 405 
     | 
    
         
            +
                rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
         
     | 
| 
      
 406 
     | 
    
         
            +
                rb_global_variable(&rbffi_StructClass);
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
                StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rb_cObject);
         
     | 
| 
      
 409 
     | 
    
         
            +
                rb_global_variable(&StructLayoutClass);
         
     | 
| 
      
 410 
     | 
    
         
            +
             
     | 
| 
      
 411 
     | 
    
         
            +
                StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
         
     | 
| 
      
 412 
     | 
    
         
            +
                rb_global_variable(&StructLayoutBuilderClass);
         
     | 
| 
      
 413 
     | 
    
         
            +
             
     | 
| 
      
 414 
     | 
    
         
            +
                StructFieldClass = rb_define_class_under(StructLayoutBuilderClass, "Field", rb_cObject);
         
     | 
| 
      
 415 
     | 
    
         
            +
                rb_global_variable(&StructFieldClass);
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
                rb_define_alloc_func(StructClass, struct_allocate);
         
     | 
| 
      
 418 
     | 
    
         
            +
                rb_define_method(StructClass, "initialize", struct_initialize, -1);
         
     | 
| 
       413 
419 
     | 
    
         | 
| 
       414 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
       415 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
       416 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
       417 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
       418 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
       419 
     | 
    
         
            -
                rb_define_alias(rb_singleton_class( 
     | 
| 
      
 420 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
         
     | 
| 
      
 421 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
         
     | 
| 
      
 422 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "alloc_inout", "new");
         
     | 
| 
      
 423 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "new_in", "new");
         
     | 
| 
      
 424 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "new_out", "new");
         
     | 
| 
      
 425 
     | 
    
         
            +
                rb_define_alias(rb_singleton_class(StructClass), "new_inout", "new");
         
     | 
| 
       420 
426 
     | 
    
         | 
| 
       421 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       422 
     | 
    
         
            -
                rb_define_private_method( 
     | 
| 
      
 427 
     | 
    
         
            +
                rb_define_method(StructClass, "pointer", struct_get_pointer, 0);
         
     | 
| 
      
 428 
     | 
    
         
            +
                rb_define_private_method(StructClass, "pointer=", struct_set_pointer, 1);
         
     | 
| 
       423 
429 
     | 
    
         | 
| 
       424 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       425 
     | 
    
         
            -
                rb_define_private_method( 
     | 
| 
      
 430 
     | 
    
         
            +
                rb_define_method(StructClass, "layout", struct_get_layout, 0);
         
     | 
| 
      
 431 
     | 
    
         
            +
                rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
         
     | 
| 
       426 
432 
     | 
    
         | 
| 
       427 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       428 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
      
 433 
     | 
    
         
            +
                rb_define_method(StructClass, "[]", struct_get_field, 1);
         
     | 
| 
      
 434 
     | 
    
         
            +
                rb_define_method(StructClass, "[]=", struct_put_field, 2);
         
     | 
| 
       429 
435 
     | 
    
         | 
| 
       430 
     | 
    
         
            -
                rb_define_alloc_func( 
     | 
| 
       431 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       432 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       433 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       434 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
     | 
    
         
            -
                rb_define_alloc_func( 
     | 
| 
       437 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       438 
     | 
    
         
            -
                rb_define_method( 
     | 
| 
       439 
     | 
    
         
            -
             
     | 
| 
       440 
     | 
    
         
            -
                 
     | 
| 
       441 
     | 
    
         
            -
                 
     | 
| 
       442 
     | 
    
         
            -
                 
     | 
| 
       443 
     | 
    
         
            -
                 
     | 
| 
      
 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");
         
     | 
| 
       444 
451 
     | 
    
         
             
                to_ptr = rb_intern("to_ptr");
         
     | 
| 
      
 452 
     | 
    
         
            +
                to_s = rb_intern("to_s");
         
     | 
| 
       445 
453 
     | 
    
         
             
                SIZE_ID = rb_intern("SIZE");
         
     | 
| 
       446 
454 
     | 
    
         
             
                ALIGN_ID = rb_intern("ALIGN");
         
     | 
| 
      
 455 
     | 
    
         
            +
                TYPE_ID = rb_intern("TYPE");
         
     | 
| 
       447 
456 
     | 
    
         
             
            #undef FIELD
         
     | 
| 
       448 
457 
     | 
    
         
             
            #define FIELD(name, typeName, nativeType, T) do { \
         
     | 
| 
       449 
458 
     | 
    
         
             
                typedef struct { char c; T v; } s; \
         
     | 
| 
       450 
     | 
    
         
            -
                    klass = rb_define_class_under( 
     | 
| 
       451 
     | 
    
         
            -
                    rb_define_const(klass, "ALIGN", INT2NUM((sizeof(s) - sizeof(T)) 
     | 
| 
       452 
     | 
    
         
            -
                    rb_define_const(klass, "SIZE", INT2NUM(sizeof(T) 
     | 
| 
      
 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))); \
         
     | 
| 
       453 
462 
     | 
    
         
             
                    rb_define_const(klass, "TYPE", INT2NUM(nativeType)); \
         
     | 
| 
       454 
463 
     | 
    
         
             
                } while(0)
         
     | 
| 
       455 
464 
     | 
    
         | 
    
        data/ext/ffi_c/Struct.h
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ 
     | 
|
| 
       7 
7 
     | 
    
         
             
            extern "C" {
         
     | 
| 
       8 
8 
     | 
    
         
             
            #endif
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                extern void  
     | 
| 
      
 10 
     | 
    
         
            +
                extern void rbffi_Struct_Init(VALUE ffiModule);
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                struct StructLayout;
         
     | 
| 
       13 
13 
     | 
    
         
             
                typedef struct Struct {
         
     | 
| 
         @@ -17,7 +17,7 @@ extern "C" { 
     | 
|
| 
       17 
17 
     | 
    
         
             
                    VALUE rbPointer;
         
     | 
| 
       18 
18 
     | 
    
         
             
                } Struct;
         
     | 
| 
       19 
19 
     | 
    
         | 
| 
       20 
     | 
    
         
            -
                extern VALUE  
     | 
| 
      
 20 
     | 
    
         
            +
                extern VALUE rbffi_StructClass;
         
     | 
| 
       21 
21 
     | 
    
         
             
            #ifdef	__cplusplus
         
     | 
| 
       22 
22 
     | 
    
         
             
            }
         
     | 
| 
       23 
23 
     | 
    
         
             
            #endif
         
     | 
    
        data/ext/ffi_c/Type.c
    ADDED
    
    | 
         @@ -0,0 +1,230 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #include <sys/param.h>
         
     | 
| 
      
 2 
     | 
    
         
            +
            #include <sys/types.h>
         
     | 
| 
      
 3 
     | 
    
         
            +
            #include <ruby.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #include <ffi.h>
         
     | 
| 
      
 5 
     | 
    
         
            +
            #include "rbffi.h"
         
     | 
| 
      
 6 
     | 
    
         
            +
            #include "compat.h"
         
     | 
| 
      
 7 
     | 
    
         
            +
            #include "Types.h"
         
     | 
| 
      
 8 
     | 
    
         
            +
            #include "Type.h"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            typedef struct BuiltinType_ {
         
     | 
| 
      
 12 
     | 
    
         
            +
                Type type;
         
     | 
| 
      
 13 
     | 
    
         
            +
                char* name;
         
     | 
| 
      
 14 
     | 
    
         
            +
            } BuiltinType;
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            static void builtin_type_free(BuiltinType *);
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            VALUE rbffi_TypeClass = Qnil;
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            static VALUE classBuiltinType = Qnil;
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 23 
     | 
    
         
            +
            type_allocate(VALUE klass)
         
     | 
| 
      
 24 
     | 
    
         
            +
            {
         
     | 
| 
      
 25 
     | 
    
         
            +
                Type* type;
         
     | 
| 
      
 26 
     | 
    
         
            +
                VALUE obj = Data_Make_Struct(klass, Type, NULL, -1, type);
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                type->nativeType = -1;
         
     | 
| 
      
 29 
     | 
    
         
            +
                type->size = 0;
         
     | 
| 
      
 30 
     | 
    
         
            +
                type->alignment = 1;
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                return obj;
         
     | 
| 
      
 33 
     | 
    
         
            +
            }
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 36 
     | 
    
         
            +
            type_initialize(VALUE self, VALUE value)
         
     | 
| 
      
 37 
     | 
    
         
            +
            {
         
     | 
| 
      
 38 
     | 
    
         
            +
                Type* type;
         
     | 
| 
      
 39 
     | 
    
         
            +
                Type* other;
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                Data_Get_Struct(self, Type, type);
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                if (FIXNUM_P(value)) {
         
     | 
| 
      
 44 
     | 
    
         
            +
                    type->nativeType = FIX2INT(value);
         
     | 
| 
      
 45 
     | 
    
         
            +
                } else if (rb_obj_is_kind_of(value, rbffi_TypeClass)) {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    Data_Get_Struct(value, Type, other);
         
     | 
| 
      
 47 
     | 
    
         
            +
                    type->nativeType = other->nativeType;
         
     | 
| 
      
 48 
     | 
    
         
            +
                    type->size = other->size;
         
     | 
| 
      
 49 
     | 
    
         
            +
                    type->alignment = other->alignment;
         
     | 
| 
      
 50 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 51 
     | 
    
         
            +
                    rb_raise(rb_eArgError, "wrong type");
         
     | 
| 
      
 52 
     | 
    
         
            +
                }
         
     | 
| 
      
 53 
     | 
    
         
            +
                
         
     | 
| 
      
 54 
     | 
    
         
            +
                return self;
         
     | 
| 
      
 55 
     | 
    
         
            +
            }
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 58 
     | 
    
         
            +
            type_size(VALUE self)
         
     | 
| 
      
 59 
     | 
    
         
            +
            {
         
     | 
| 
      
 60 
     | 
    
         
            +
                Type *type;
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                Data_Get_Struct(self, Type, type);
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                return INT2FIX(type->size);
         
     | 
| 
      
 65 
     | 
    
         
            +
            }
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 68 
     | 
    
         
            +
            type_alignment(VALUE self)
         
     | 
| 
      
 69 
     | 
    
         
            +
            {
         
     | 
| 
      
 70 
     | 
    
         
            +
                Type *type;
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                Data_Get_Struct(self, Type, type);
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                return INT2FIX(type->alignment);
         
     | 
| 
      
 75 
     | 
    
         
            +
            }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 78 
     | 
    
         
            +
            type_inspect(VALUE self)
         
     | 
| 
      
 79 
     | 
    
         
            +
            {
         
     | 
| 
      
 80 
     | 
    
         
            +
                char buf[256];
         
     | 
| 
      
 81 
     | 
    
         
            +
                Type *type;
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                Data_Get_Struct(self, Type, type);
         
     | 
| 
      
 84 
     | 
    
         
            +
                snprintf(buf, sizeof(buf), "#<FFI::Type:%p size=%d alignment=%d>", 
         
     | 
| 
      
 85 
     | 
    
         
            +
                        type, type->size, type->alignment);
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                return rb_str_new2(buf);
         
     | 
| 
      
 88 
     | 
    
         
            +
            }
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 91 
     | 
    
         
            +
            enum_allocate(VALUE klass)
         
     | 
| 
      
 92 
     | 
    
         
            +
            {
         
     | 
| 
      
 93 
     | 
    
         
            +
                Type* type;
         
     | 
| 
      
 94 
     | 
    
         
            +
                VALUE obj;
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                obj = Data_Make_Struct(klass, Type, NULL, -1, type);
         
     | 
| 
      
 97 
     | 
    
         
            +
                type->nativeType = NATIVE_ENUM;
         
     | 
| 
      
 98 
     | 
    
         
            +
                type->ffiType = &ffi_type_sint;
         
     | 
| 
      
 99 
     | 
    
         
            +
                type->size = ffi_type_sint.size;
         
     | 
| 
      
 100 
     | 
    
         
            +
                type->alignment = ffi_type_sint.alignment;
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                return obj;
         
     | 
| 
      
 103 
     | 
    
         
            +
            }
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            int
         
     | 
| 
      
 106 
     | 
    
         
            +
            rbffi_Type_GetIntValue(VALUE type)
         
     | 
| 
      
 107 
     | 
    
         
            +
            {
         
     | 
| 
      
 108 
     | 
    
         
            +
                if (rb_obj_is_kind_of(type, rbffi_TypeClass)) {
         
     | 
| 
      
 109 
     | 
    
         
            +
                    Type* t;
         
     | 
| 
      
 110 
     | 
    
         
            +
                    Data_Get_Struct(type, Type, t);
         
     | 
| 
      
 111 
     | 
    
         
            +
                    return t->nativeType;
         
     | 
| 
      
 112 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 113 
     | 
    
         
            +
                    rb_raise(rb_eArgError, "Invalid type argument");
         
     | 
| 
      
 114 
     | 
    
         
            +
                }
         
     | 
| 
      
 115 
     | 
    
         
            +
            }
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 118 
     | 
    
         
            +
            builtin_type_new(VALUE klass, int nativeType, ffi_type* ffiType, const char* name)
         
     | 
| 
      
 119 
     | 
    
         
            +
            {
         
     | 
| 
      
 120 
     | 
    
         
            +
                BuiltinType* type;
         
     | 
| 
      
 121 
     | 
    
         
            +
                VALUE obj = Data_Make_Struct(klass, BuiltinType, NULL, builtin_type_free, type);
         
     | 
| 
      
 122 
     | 
    
         
            +
                
         
     | 
| 
      
 123 
     | 
    
         
            +
                type->name = strdup(name);
         
     | 
| 
      
 124 
     | 
    
         
            +
                type->type.nativeType = nativeType;
         
     | 
| 
      
 125 
     | 
    
         
            +
                type->type.ffiType = ffiType;
         
     | 
| 
      
 126 
     | 
    
         
            +
                type->type.size = ffiType->size;
         
     | 
| 
      
 127 
     | 
    
         
            +
                type->type.alignment = ffiType->alignment;
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                return obj;
         
     | 
| 
      
 130 
     | 
    
         
            +
            }
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            static void
         
     | 
| 
      
 133 
     | 
    
         
            +
            builtin_type_free(BuiltinType *type)
         
     | 
| 
      
 134 
     | 
    
         
            +
            {
         
     | 
| 
      
 135 
     | 
    
         
            +
                free(type->name);
         
     | 
| 
      
 136 
     | 
    
         
            +
                xfree(type);
         
     | 
| 
      
 137 
     | 
    
         
            +
            }
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            static VALUE
         
     | 
| 
      
 140 
     | 
    
         
            +
            builtin_type_inspect(VALUE self)
         
     | 
| 
      
 141 
     | 
    
         
            +
            {
         
     | 
| 
      
 142 
     | 
    
         
            +
                char buf[256];
         
     | 
| 
      
 143 
     | 
    
         
            +
                BuiltinType *type;
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                Data_Get_Struct(self, BuiltinType, type);
         
     | 
| 
      
 146 
     | 
    
         
            +
                snprintf(buf, sizeof(buf), "#<FFI::Type::Builtin:%ssize=%d alignment=%d>",
         
     | 
| 
      
 147 
     | 
    
         
            +
                        type->name, type->type.size, type->type.alignment);
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                return rb_str_new2(buf);
         
     | 
| 
      
 150 
     | 
    
         
            +
            }
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
            void
         
     | 
| 
      
 153 
     | 
    
         
            +
            rbffi_Type_Init(VALUE moduleFFI)
         
     | 
| 
      
 154 
     | 
    
         
            +
            {
         
     | 
| 
      
 155 
     | 
    
         
            +
                VALUE moduleNativeType;
         
     | 
| 
      
 156 
     | 
    
         
            +
                VALUE classType = rbffi_TypeClass = rb_define_class_under(moduleFFI, "Type", rb_cObject);
         
     | 
| 
      
 157 
     | 
    
         
            +
                VALUE classEnum =  rb_define_class_under(moduleFFI, "Enum", classType);
         
     | 
| 
      
 158 
     | 
    
         
            +
                classBuiltinType = rb_define_class_under(rbffi_TypeClass, "Builtin", rbffi_TypeClass);
         
     | 
| 
      
 159 
     | 
    
         
            +
                moduleNativeType = rb_define_module_under(moduleFFI, "NativeType");
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                rb_global_variable(&rbffi_TypeClass);
         
     | 
| 
      
 162 
     | 
    
         
            +
                rb_global_variable(&classBuiltinType);
         
     | 
| 
      
 163 
     | 
    
         
            +
                rb_global_variable(&moduleNativeType);
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                rb_define_alloc_func(classType, type_allocate);
         
     | 
| 
      
 166 
     | 
    
         
            +
                rb_define_method(classType, "initialize", type_initialize, 1);
         
     | 
| 
      
 167 
     | 
    
         
            +
                rb_define_method(classType, "size", type_size, 0);
         
     | 
| 
      
 168 
     | 
    
         
            +
                rb_define_method(classType, "alignment", type_alignment, 0);
         
     | 
| 
      
 169 
     | 
    
         
            +
                rb_define_method(classBuiltinType, "inspect", type_inspect, 0);
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                // Make Type::Builtin non-allocatable
         
     | 
| 
      
 172 
     | 
    
         
            +
                rb_undef_method(CLASS_OF(classBuiltinType), "new");
         
     | 
| 
      
 173 
     | 
    
         
            +
                rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                rb_define_alloc_func(classEnum, enum_allocate);
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                rb_global_variable(&rbffi_TypeClass);
         
     | 
| 
      
 178 
     | 
    
         
            +
                rb_global_variable(&classBuiltinType);
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                // Define all the builtin types
         
     | 
| 
      
 181 
     | 
    
         
            +
                #define T(x, ffiType) do { \
         
     | 
| 
      
 182 
     | 
    
         
            +
                    VALUE t = Qnil; \
         
     | 
| 
      
 183 
     | 
    
         
            +
                    rb_define_const(classType, #x, t = builtin_type_new(classBuiltinType, NATIVE_##x, ffiType, #x)); \
         
     | 
| 
      
 184 
     | 
    
         
            +
                    rb_define_const(moduleNativeType, #x, t); \
         
     | 
| 
      
 185 
     | 
    
         
            +
                    rb_define_const(moduleFFI, "TYPE_" #x, t); \
         
     | 
| 
      
 186 
     | 
    
         
            +
                } while(0)
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
                T(VOID, &ffi_type_void);
         
     | 
| 
      
 189 
     | 
    
         
            +
                T(INT8, &ffi_type_sint8);
         
     | 
| 
      
 190 
     | 
    
         
            +
                T(UINT8, &ffi_type_uint8);
         
     | 
| 
      
 191 
     | 
    
         
            +
                T(INT16, &ffi_type_sint16);
         
     | 
| 
      
 192 
     | 
    
         
            +
                T(UINT16, &ffi_type_uint16);
         
     | 
| 
      
 193 
     | 
    
         
            +
                T(INT32, &ffi_type_sint32);
         
     | 
| 
      
 194 
     | 
    
         
            +
                T(UINT32, &ffi_type_uint32);
         
     | 
| 
      
 195 
     | 
    
         
            +
                T(INT64, &ffi_type_sint64);
         
     | 
| 
      
 196 
     | 
    
         
            +
                T(UINT64, &ffi_type_uint64);
         
     | 
| 
      
 197 
     | 
    
         
            +
                T(FLOAT32, &ffi_type_float);
         
     | 
| 
      
 198 
     | 
    
         
            +
                T(FLOAT64, &ffi_type_double);
         
     | 
| 
      
 199 
     | 
    
         
            +
                T(POINTER, &ffi_type_pointer);
         
     | 
| 
      
 200 
     | 
    
         
            +
                T(STRING, &ffi_type_pointer);
         
     | 
| 
      
 201 
     | 
    
         
            +
                T(RBXSTRING, &ffi_type_pointer);
         
     | 
| 
      
 202 
     | 
    
         
            +
                T(BUFFER_IN, &ffi_type_pointer);
         
     | 
| 
      
 203 
     | 
    
         
            +
                T(BUFFER_OUT, &ffi_type_pointer);
         
     | 
| 
      
 204 
     | 
    
         
            +
                T(BUFFER_INOUT, &ffi_type_pointer);
         
     | 
| 
      
 205 
     | 
    
         
            +
                T(ENUM, &ffi_type_sint);
         
     | 
| 
      
 206 
     | 
    
         
            +
                T(BOOL, &ffi_type_sint);
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                T(CHAR_ARRAY, &ffi_type_void);
         
     | 
| 
      
 210 
     | 
    
         
            +
                T(VARARGS, &ffi_type_void);
         
     | 
| 
      
 211 
     | 
    
         
            +
                
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                if (sizeof(long) == 4) {
         
     | 
| 
      
 214 
     | 
    
         
            +
                    VALUE t = Qnil;
         
     | 
| 
      
 215 
     | 
    
         
            +
                    rb_define_const(classType, "LONG", t = builtin_type_new(classBuiltinType, NATIVE_INT32, &ffi_type_slong, "LONG"));
         
     | 
| 
      
 216 
     | 
    
         
            +
                    rb_define_const(moduleNativeType, "LONG", t);
         
     | 
| 
      
 217 
     | 
    
         
            +
                    rb_define_const(moduleFFI, "TYPE_LONG", t);
         
     | 
| 
      
 218 
     | 
    
         
            +
                    rb_define_const(classType, "ULONG", t = builtin_type_new(classBuiltinType, NATIVE_UINT32, &ffi_type_slong, "ULONG"));
         
     | 
| 
      
 219 
     | 
    
         
            +
                    rb_define_const(moduleNativeType, "ULONG", t);
         
     | 
| 
      
 220 
     | 
    
         
            +
                    rb_define_const(moduleFFI, "TYPE_ULONG", t);
         
     | 
| 
      
 221 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 222 
     | 
    
         
            +
                    VALUE t = Qnil;
         
     | 
| 
      
 223 
     | 
    
         
            +
                    rb_define_const(classType, "LONG", t = builtin_type_new(classBuiltinType, NATIVE_INT64, &ffi_type_slong, "LONG"));
         
     | 
| 
      
 224 
     | 
    
         
            +
                    rb_define_const(moduleNativeType, "LONG", t);
         
     | 
| 
      
 225 
     | 
    
         
            +
                    rb_define_const(moduleFFI, "TYPE_LONG", t);
         
     | 
| 
      
 226 
     | 
    
         
            +
                    rb_define_const(classType, "ULONG", t = builtin_type_new(classBuiltinType, NATIVE_UINT64, &ffi_type_slong, "ULONG"));
         
     | 
| 
      
 227 
     | 
    
         
            +
                    rb_define_const(moduleNativeType, "ULONG", t);
         
     | 
| 
      
 228 
     | 
    
         
            +
                    rb_define_const(moduleFFI, "TYPE_ULONG", t);
         
     | 
| 
      
 229 
     | 
    
         
            +
                }
         
     | 
| 
      
 230 
     | 
    
         
            +
            }
         
     |