ffi 0.3.1 → 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.
Files changed (76) hide show
  1. data/README.rdoc +51 -1
  2. data/Rakefile +38 -28
  3. data/ext/ffi_c/AbstractMemory.c +74 -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 +42 -24
  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 +152 -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 +27 -20
  16. data/ext/ffi_c/MemoryPointer.h +3 -3
  17. data/ext/ffi_c/NullPointer.c +51 -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 +48 -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 +21 -44
  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/gen/Rakefile +12 -0
  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 +79 -18
  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/lib/ffi.rb +10 -1
  47. data/spec/ffi/bool_spec.rb +24 -0
  48. data/spec/ffi/callback_spec.rb +217 -17
  49. data/spec/ffi/enum_spec.rb +164 -0
  50. data/spec/ffi/managed_struct_spec.rb +6 -1
  51. data/spec/ffi/number_spec.rb +30 -0
  52. data/spec/ffi/pointer_spec.rb +33 -8
  53. data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
  54. data/spec/ffi/spec_helper.rb +5 -1
  55. data/spec/ffi/string_spec.rb +65 -4
  56. data/spec/ffi/struct_callback_spec.rb +41 -0
  57. data/spec/ffi/struct_initialize_spec.rb +30 -0
  58. data/spec/ffi/struct_spec.rb +44 -21
  59. metadata +31 -69
  60. data/ext/ffi_c/ffi.mk +0 -23
  61. data/nbproject/Makefile-Default.mk +0 -57
  62. data/nbproject/Makefile-impl.mk +0 -123
  63. data/nbproject/Package-Default.bash +0 -72
  64. data/nbproject/configurations.xml +0 -293
  65. data/nbproject/private/configurations.xml +0 -22
  66. data/nbproject/private/private.xml +0 -7
  67. data/nbproject/project.properties +0 -0
  68. data/nbproject/project.xml +0 -15
  69. data/samples/getlogin.rb +0 -7
  70. data/samples/getpid.rb +0 -7
  71. data/samples/gettimeofday.rb +0 -17
  72. data/samples/hello.rb +0 -6
  73. data/samples/inotify.rb +0 -59
  74. data/samples/pty.rb +0 -75
  75. data/samples/qsort.rb +0 -20
  76. data/samples/sample_helper.rb +0 -6
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 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
 
data/ext/ffi_c/Struct.h CHANGED
@@ -7,7 +7,7 @@
7
7
  extern "C" {
8
8
  #endif
9
9
 
10
- void rb_FFI_Struct_Init();
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
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
+ }
data/ext/ffi_c/Type.h ADDED
@@ -0,0 +1,28 @@
1
+ #ifndef _TYPE_H
2
+ #define _TYPE_H
3
+
4
+ #include <ruby.h>
5
+ #include <ffi.h>
6
+
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif
10
+
11
+
12
+ typedef struct Type_ {
13
+ NativeType nativeType;
14
+ ffi_type* ffiType;
15
+ int size;
16
+ int alignment;
17
+ } Type;
18
+
19
+ extern VALUE rbffi_TypeClass;
20
+ extern int rbffi_Type_GetIntValue(VALUE type);
21
+
22
+
23
+ #ifdef __cplusplus
24
+ }
25
+ #endif
26
+
27
+ #endif /* _TYPE_H */
28
+
data/ext/ffi_c/Types.c CHANGED
@@ -1,9 +1,13 @@
1
1
  #include <ruby.h>
2
2
  #include "Pointer.h"
3
+ #include "rbffi.h"
4
+ #include "Callback.h"
3
5
  #include "Types.h"
4
6
 
7
+ static ID id_find = 0;
8
+
5
9
  ffi_type*
6
- rb_FFI_NativeTypeToFFI(NativeType type)
10
+ rbffi_NativeType_ToFFI(NativeType type)
7
11
  {
8
12
  switch (type) {
9
13
  case NATIVE_VOID:
@@ -16,7 +20,9 @@ rb_FFI_NativeTypeToFFI(NativeType type)
16
20
  return &ffi_type_sint16;
17
21
  case NATIVE_UINT16:
18
22
  return &ffi_type_uint16;
23
+ case NATIVE_BOOL:
19
24
  case NATIVE_INT32:
25
+ case NATIVE_ENUM:
20
26
  return &ffi_type_sint32;
21
27
  case NATIVE_UINT32:
22
28
  return &ffi_type_uint32;
@@ -34,6 +40,7 @@ rb_FFI_NativeTypeToFFI(NativeType type)
34
40
  case NATIVE_BUFFER_IN:
35
41
  case NATIVE_BUFFER_OUT:
36
42
  case NATIVE_BUFFER_INOUT:
43
+ case NATIVE_CALLBACK:
37
44
  return &ffi_type_pointer;
38
45
  default:
39
46
  return NULL;
@@ -41,9 +48,9 @@ rb_FFI_NativeTypeToFFI(NativeType type)
41
48
  }
42
49
 
43
50
  VALUE
44
- rb_FFI_NativeValueToRuby(NativeType type, const void* ptr)
51
+ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
45
52
  {
46
- switch (type) {
53
+ switch (type->nativeType) {
47
54
  case NATIVE_VOID:
48
55
  return Qnil;
49
56
  case NATIVE_INT8:
@@ -67,10 +74,45 @@ rb_FFI_NativeValueToRuby(NativeType type, const void* ptr)
67
74
  case NATIVE_FLOAT64:
68
75
  return rb_float_new(*(double *) ptr);
69
76
  case NATIVE_STRING:
70
- return rb_tainted_str_new2(*(char **) ptr);
77
+ return (*(char **)ptr) ? rb_tainted_str_new2(*(char **) ptr) : Qnil;
71
78
  case NATIVE_POINTER:
72
- return rb_FFI_Pointer_new(*(void **) ptr);
79
+ return rbffi_Pointer_NewInstance(*(void **) ptr);
80
+ case NATIVE_BOOL:
81
+ return ((int) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
82
+ case NATIVE_ENUM:
83
+ {
84
+ VALUE enum_obj = rb_funcall(enums, id_find, 1, rbType);
85
+ if (enum_obj == Qnil) {
86
+ VALUE s = rb_inspect(rbType);
87
+ rb_raise(rb_eRuntimeError, "Unknown enumeration: %s", StringValueCStr(s));
88
+ }
89
+ return rb_funcall(enum_obj, id_find, 1, INT2NUM((unsigned int) *(ffi_arg *) ptr));
90
+ }
91
+ case NATIVE_CALLBACK: {
92
+ CallbackInfo* cbInfo;
93
+ VALUE argv[6];
94
+ VALUE funcptr = rbffi_Pointer_NewInstance(*(void **) ptr);
95
+
96
+ Data_Get_Struct(rbType, CallbackInfo, cbInfo);
97
+ argv[0] = funcptr;
98
+ argv[1] = cbInfo->rbParameterTypes;
99
+ argv[2] = ID2SYM(rb_intern("cb")); // just shove a dummy value
100
+ argv[3] = cbInfo->rbReturnType;
101
+ argv[4] = rb_str_new2("default");
102
+ argv[5] = Qnil;
103
+
104
+ return rb_class_new_instance(6, argv, rbffi_InvokerClass);
105
+ }
106
+
73
107
  default:
74
- rb_raise(rb_eRuntimeError, "Unknown type: %d", type);
108
+ rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
109
+ return Qnil;
75
110
  }
76
111
  }
112
+
113
+ void
114
+ rbffi_Types_Init(VALUE moduleFFI)
115
+ {
116
+ id_find = rb_intern("find");
117
+ }
118
+
data/ext/ffi_c/Types.h CHANGED
@@ -25,6 +25,7 @@ typedef enum {
25
25
  NATIVE_BUFFER_OUT,
26
26
  NATIVE_BUFFER_INOUT,
27
27
  NATIVE_CHAR_ARRAY,
28
+ NATIVE_BOOL,
28
29
 
29
30
  /**
30
31
  * An immutable string. Nul terminated, but only copies in to the native function
@@ -34,11 +35,16 @@ typedef enum {
34
35
  NATIVE_RBXSTRING,
35
36
  /** The function takes a variable number of arguments */
36
37
  NATIVE_VARARGS,
38
+ /** A typedef-ed enum */
39
+ NATIVE_ENUM,
37
40
  } NativeType;
38
41
 
39
42
  #include <ffi.h>
40
- extern ffi_type* rb_FFI_NativeTypeToFFI(NativeType type);
41
- VALUE rb_FFI_NativeValueToRuby(NativeType type, const void* ptr);
43
+ #include "Type.h"
44
+
45
+ extern ffi_type* rbffi_NativeType_ToFFI(NativeType type);
46
+ VALUE rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums);
47
+ void rbffi_Types_Init(VALUE moduleFFI);
42
48
 
43
49
  #ifdef __cplusplus
44
50
  }
@@ -0,0 +1,40 @@
1
+ #ifndef JFFI_ENDIAN_H
2
+ #define JFFI_ENDIAN_H
3
+
4
+ #include <sys/param.h>
5
+ #include <sys/types.h>
6
+
7
+ #ifdef __linux__
8
+ # include_next <endian.h>
9
+ #endif
10
+
11
+ #ifdef __sun
12
+ # include <sys/byteorder.h>
13
+ # define LITTLE_ENDIAN 1234
14
+ # define BIG_ENDIAN 4321
15
+ # if defined(_BIG_ENDIAN)
16
+ # define BYTE_ORDER BIG_ENDIAN
17
+ # elif defined(_LITTLE_ENDIAN)
18
+ # define BYTE_ORDER LITTLE_ENDIAN
19
+ # else
20
+ # error "Cannot determine endian-ness"
21
+ # endif
22
+ #endif
23
+
24
+ #if defined(_AIX) && !defined(BYTE_ORDER)
25
+ # define LITTLE_ENDIAN 1234
26
+ # define BIG_ENDIAN 4321
27
+ # if defined(__BIG_ENDIAN__)
28
+ # define BYTE_ORDER BIG_ENDIAN
29
+ # elif defined(__LITTLE_ENDIAN__)
30
+ # define BYTE_ORDER LITTLE_ENDIAN
31
+ # else
32
+ # error "Cannot determine endian-ness"
33
+ # endif
34
+ #endif
35
+
36
+ #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
37
+ # error "Cannot determine the endian-ness of this platform"
38
+ #endif
39
+
40
+ #endif /* JFFI_ENDIAN_H */