ffi 0.3.5 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (59) hide show
  1. data/README.rdoc +51 -1
  2. data/Rakefile +34 -26
  3. data/ext/ffi_c/AbstractMemory.c +73 -70
  4. data/ext/ffi_c/AbstractMemory.h +8 -4
  5. data/ext/ffi_c/AutoPointer.c +8 -9
  6. data/ext/ffi_c/AutoPointer.h +2 -2
  7. data/ext/ffi_c/Buffer.c +19 -20
  8. data/ext/ffi_c/Callback.c +85 -33
  9. data/ext/ffi_c/Callback.h +11 -5
  10. data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +83 -16
  11. data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
  12. data/ext/ffi_c/Invoker.c +148 -192
  13. data/ext/ffi_c/LastError.c +135 -0
  14. data/ext/ffi_c/LastError.h +18 -0
  15. data/ext/ffi_c/MemoryPointer.c +26 -19
  16. data/ext/ffi_c/MemoryPointer.h +3 -3
  17. data/ext/ffi_c/NullPointer.c +49 -47
  18. data/ext/ffi_c/Platform.c +9 -10
  19. data/ext/ffi_c/Platform.h +1 -1
  20. data/ext/ffi_c/Pointer.c +52 -21
  21. data/ext/ffi_c/Pointer.h +8 -6
  22. data/ext/ffi_c/Struct.c +70 -61
  23. data/ext/ffi_c/Struct.h +2 -2
  24. data/ext/ffi_c/Type.c +230 -0
  25. data/ext/ffi_c/Type.h +28 -0
  26. data/ext/ffi_c/Types.c +47 -6
  27. data/ext/ffi_c/Types.h +8 -2
  28. data/ext/ffi_c/endian.h +40 -0
  29. data/ext/ffi_c/extconf.rb +6 -5
  30. data/ext/ffi_c/ffi.c +20 -43
  31. data/ext/ffi_c/libffi.bsd.mk +34 -0
  32. data/ext/ffi_c/libffi.darwin.mk +30 -10
  33. data/ext/ffi_c/libffi.gnu.mk +29 -0
  34. data/ext/ffi_c/libffi.mk +4 -2
  35. data/ext/ffi_c/rbffi.h +6 -8
  36. data/lib/ffi.rb +10 -1
  37. data/lib/ffi/autopointer.rb +1 -1
  38. data/lib/ffi/enum.rb +78 -0
  39. data/lib/ffi/ffi.rb +5 -6
  40. data/lib/ffi/io.rb +15 -1
  41. data/lib/ffi/library.rb +78 -17
  42. data/lib/ffi/pointer.rb +2 -2
  43. data/lib/ffi/struct.rb +68 -14
  44. data/lib/ffi/types.rb +6 -3
  45. data/lib/ffi/variadic.rb +2 -2
  46. data/spec/ffi/bool_spec.rb +24 -0
  47. data/spec/ffi/callback_spec.rb +217 -17
  48. data/spec/ffi/enum_spec.rb +164 -0
  49. data/spec/ffi/managed_struct_spec.rb +6 -1
  50. data/spec/ffi/number_spec.rb +30 -0
  51. data/spec/ffi/pointer_spec.rb +33 -8
  52. data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
  53. data/spec/ffi/spec_helper.rb +5 -1
  54. data/spec/ffi/string_spec.rb +65 -4
  55. data/spec/ffi/struct_callback_spec.rb +41 -0
  56. data/spec/ffi/struct_initialize_spec.rb +30 -0
  57. data/spec/ffi/struct_spec.rb +19 -20
  58. metadata +29 -52
  59. data/ext/ffi_c/ffi.mk +0 -23
@@ -11,26 +11,25 @@ typedef struct Pointer {
11
11
  VALUE parent;
12
12
  } Pointer;
13
13
 
14
- #define POINTER(obj) rb_FFI_AbstractMemory_cast((obj), rb_FFI_Pointer_class)
14
+ #define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass)
15
15
 
16
- VALUE rb_FFI_Pointer_class;
17
- static VALUE classPointer = Qnil;
16
+ VALUE rbffi_PointerClass;
18
17
  static void ptr_mark(Pointer* ptr);
19
18
 
20
19
  VALUE
21
- rb_FFI_Pointer_new(void* addr)
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 rb_FFI_NullPointer_singleton;
26
+ return rbffi_NullPointerSingleton;
28
27
  }
29
28
 
30
- obj = Data_Make_Struct(classPointer, Pointer, NULL, -1, p);
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 = &rb_FFI_AbstractMemory_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(classPointer, Pointer, NULL, -1, p);
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(classPointer, Pointer, ptr_mark, -1, p);
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 = &rb_FFI_AbstractMemory_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
- rb_FFI_Pointer_Init()
151
+ rbffi_Pointer_Init(VALUE moduleFFI)
122
152
  {
123
- VALUE moduleFFI = rb_define_module("FFI");
124
- rb_FFI_Pointer_class = classPointer = rb_define_class_under(moduleFFI, "Pointer", rb_FFI_AbstractMemory_class);
125
- rb_global_variable(&rb_FFI_Pointer_class);
126
-
127
- rb_define_alloc_func(classPointer, ptr_allocate);
128
- rb_define_method(classPointer, "inspect", ptr_inspect, 0);
129
- rb_define_method(classPointer, "+", ptr_plus, 1);
130
- rb_define_method(classPointer, "null?", ptr_null_p, 0);
131
- rb_define_method(classPointer, "address", ptr_address, 0);
132
- rb_define_method(classPointer, "==", ptr_equals, 1);
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
  }
@@ -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
  }
@@ -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 rb_FFI_Struct_class = Qnil;
37
- static VALUE classStruct = Qnil, classStructLayout = Qnil;
38
- static VALUE classStructField = Qnil, classStructLayoutBuilder = Qnil;
39
- static ID pointerID = 0, layoutID = 0, SIZE_ID, ALIGN_ID;
40
- static ID getID = 0, putID = 0, to_ptr = 0;
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), rb_intern("TYPE"))) {
62
- field->type = NUM2UINT(rb_const_get(CLASS_OF(self), rb_intern("TYPE")));
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, rb_intern("SIZE")));
69
- field->align = NUM2UINT(rb_const_get(klass, rb_intern("ALIGN")));
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), rb_intern("layout"), RARRAY_LEN(rest), RARRAY_PTR(rest));
155
- } else if (rb_cvar_defined(klass, layoutID)) {
156
- s->rbLayout = rb_cvar_get(klass, layoutID);
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, classStructLayout)) {
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 = rb_FFI_MemoryPointer_new(s->layout->size, 1, true);
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, rb_intern("to_s"), 0, NULL);
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, getID, 1, &s->rbPointer);
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, putID, 2, argv);
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, rb_FFI_AbstractMemory_class)) {
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, pointerID, pointer);
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, classStructLayout)) {
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, layoutID, layout);
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, classStructField)) {
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
- rb_FFI_Struct_Init()
402
+ rbffi_Struct_Init(VALUE moduleFFI)
403
403
  {
404
- VALUE moduleFFI = rb_define_module("FFI");
405
- VALUE klass;
406
- rb_FFI_Struct_class = classStruct = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
407
- classStructLayout = rb_define_class_under(moduleFFI, "StructLayout", rb_cObject);
408
- classStructLayoutBuilder = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
409
- classStructField = rb_define_class_under(classStructLayoutBuilder, "Field", rb_cObject);
410
-
411
- rb_define_alloc_func(classStruct, struct_allocate);
412
- rb_define_method(classStruct, "initialize", struct_initialize, -1);
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(classStruct), "alloc_in", "new");
415
- rb_define_alias(rb_singleton_class(classStruct), "alloc_out", "new");
416
- rb_define_alias(rb_singleton_class(classStruct), "alloc_inout", "new");
417
- rb_define_alias(rb_singleton_class(classStruct), "new_in", "new");
418
- rb_define_alias(rb_singleton_class(classStruct), "new_out", "new");
419
- rb_define_alias(rb_singleton_class(classStruct), "new_inout", "new");
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(classStruct, "pointer", struct_get_pointer, 0);
422
- rb_define_private_method(classStruct, "pointer=", struct_set_pointer, 1);
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(classStruct, "layout", struct_get_layout, 0);
425
- rb_define_private_method(classStruct, "layout=", struct_set_layout, 1);
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(classStruct, "[]", struct_get_field, 1);
428
- rb_define_method(classStruct, "[]=", struct_put_field, 2);
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(classStructField, struct_field_allocate);
431
- rb_define_method(classStructField, "initialize", struct_field_initialize, -1);
432
- rb_define_method(classStructField, "offset", struct_field_offset, 0);
433
- rb_define_method(classStructField, "put", struct_field_put, 2);
434
- rb_define_method(classStructField, "get", struct_field_get, 1);
435
-
436
- rb_define_alloc_func(classStructLayout, struct_layout_allocate);
437
- rb_define_method(classStructLayout, "initialize", struct_layout_initialize, 4);
438
- rb_define_method(classStructLayout, "[]", struct_layout_aref, 1);
439
-
440
- pointerID = rb_intern("@pointer");
441
- layoutID = rb_intern("@layout");
442
- getID = rb_intern("get");
443
- putID = rb_intern("put");
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(classStructLayoutBuilder, #name, classStructField); \
451
- rb_define_const(klass, "ALIGN", INT2NUM((sizeof(s) - sizeof(T)) * 8)); \
452
- rb_define_const(klass, "SIZE", INT2NUM(sizeof(T)* 8)); \
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
 
@@ -7,7 +7,7 @@
7
7
  extern "C" {
8
8
  #endif
9
9
 
10
- extern void rb_FFI_Struct_Init(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 rb_FFI_Struct_class;
20
+ extern VALUE rbffi_StructClass;
21
21
  #ifdef __cplusplus
22
22
  }
23
23
  #endif
@@ -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
+ }