ffi 0.3.0 → 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 +47 -28
  3. data/ext/ffi_c/AbstractMemory.c +149 -65
  4. data/ext/ffi_c/AbstractMemory.h +34 -4
  5. data/ext/ffi_c/AutoPointer.c +15 -18
  6. data/ext/ffi_c/AutoPointer.h +2 -2
  7. data/ext/ffi_c/Buffer.c +79 -44
  8. data/ext/ffi_c/Callback.c +133 -62
  9. data/ext/ffi_c/Callback.h +11 -5
  10. data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +88 -24
  11. data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
  12. data/ext/ffi_c/Invoker.c +154 -190
  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 +30 -20
  16. data/ext/ffi_c/MemoryPointer.h +3 -3
  17. data/ext/ffi_c/NullPointer.c +67 -28
  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 +67 -30
  21. data/ext/ffi_c/Pointer.h +8 -6
  22. data/ext/ffi_c/Struct.c +202 -267
  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/Buffer.c CHANGED
@@ -18,14 +18,31 @@ static void buffer_release(Buffer* ptr);
18
18
  static void buffer_mark(Buffer* ptr);
19
19
  static VALUE buffer_free(VALUE self);
20
20
 
21
- static VALUE classBuffer = Qnil;
22
- #define BUFFER(obj) ((Buffer *) rb_FFI_AbstractMemory_cast((obj), classBuffer))
21
+ static VALUE BufferClass = Qnil;
22
+ #define BUFFER(obj) ((Buffer *) rbffi_AbstractMemory_Cast((obj), BufferClass))
23
23
 
24
24
  static VALUE
25
25
  buffer_allocate(VALUE klass)
26
26
  {
27
27
  Buffer* buffer;
28
- return Data_Make_Struct(klass, Buffer, buffer_mark, buffer_release, buffer);
28
+ VALUE obj;
29
+
30
+ obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
31
+ buffer->parent = Qnil;
32
+ buffer->memory.ops = &rbffi_AbstractMemoryOps;
33
+
34
+ return obj;
35
+ }
36
+
37
+ static void
38
+ buffer_release(Buffer* ptr)
39
+ {
40
+ if (ptr->storage != NULL) {
41
+ free(ptr->storage);
42
+ ptr->storage = NULL;
43
+ }
44
+
45
+ xfree(ptr);
29
46
  }
30
47
 
31
48
  static VALUE
@@ -33,28 +50,30 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
33
50
  {
34
51
  VALUE size = Qnil, count = Qnil, clear = Qnil;
35
52
  Buffer* p;
36
- unsigned long msize;
37
- void* memory;
38
53
  int nargs;
39
54
 
55
+ Data_Get_Struct(self, Buffer, p);
56
+
40
57
  nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
41
- msize = rb_FFI_type_size(size) * (nargs > 1 ? NUM2LONG(count) : 1);
42
- memory = malloc(msize + 7);
43
- if (memory == NULL) {
44
- rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", msize);
58
+ p->type_size = rbffi_type_size(size);
59
+ p->memory.size = p->type_size * (nargs > 1 ? NUM2LONG(count) : 1);
60
+
61
+ p->storage = malloc(p->memory.size + 7);
62
+ if (p->storage == NULL) {
63
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", p->memory.size);
45
64
  }
46
- Data_Get_Struct(self, Buffer, p);
47
- p->storage = memory;
48
- p->memory.size = msize;
65
+
49
66
  /* ensure the memory is aligned on at least a 8 byte boundary */
50
- p->memory.address = (void *) (((uintptr_t) memory + 0x7) & (uintptr_t) ~0x7UL);
51
- p->parent = Qnil;
52
- if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
67
+ p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
68
+
69
+ if (nargs > 2 && (RTEST(clear) || clear == Qnil) && p->memory.size > 0) {
53
70
  memset(p->memory.address, 0, p->memory.size);
54
71
  }
72
+
55
73
  if (rb_block_given_p()) {
56
- return rb_rescue(rb_yield, self, buffer_free, self);
74
+ return rb_ensure(rb_yield, self, buffer_free, self);
57
75
  }
76
+
58
77
  return self;
59
78
  }
60
79
 
@@ -73,18 +92,41 @@ buffer_plus(VALUE self, VALUE offset)
73
92
  long off = NUM2LONG(offset);
74
93
 
75
94
  checkBounds(&ptr->memory, off, 1);
76
- retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, buffer_release, p);
77
- p->memory.address = ptr->memory.address + off;;
95
+
96
+ retval = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, p);
97
+ p->memory.address = ptr->memory.address + off;
78
98
  p->memory.size = ptr->memory.size - off;
99
+ p->memory.ops = &rbffi_AbstractMemoryOps;
79
100
  p->parent = self;
101
+
80
102
  return retval;
81
103
  }
82
104
 
105
+ static VALUE
106
+ buffer_aref(VALUE self, VALUE offset)
107
+ {
108
+ Buffer* ptr;
109
+
110
+ Data_Get_Struct(self, Buffer, ptr);
111
+ return buffer_plus(self, INT2FIX(ptr->type_size * NUM2INT(offset)));
112
+ }
113
+
114
+ static VALUE
115
+ buffer_type_size(VALUE self)
116
+ {
117
+ Buffer* ptr;
118
+
119
+ Data_Get_Struct(self, Buffer, ptr);
120
+ return INT2NUM(ptr->type_size);
121
+ }
122
+
83
123
  static VALUE
84
124
  buffer_inspect(VALUE self)
85
125
  {
86
126
  char tmp[100];
127
+
87
128
  snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
129
+
88
130
  return rb_str_new2(tmp);
89
131
  }
90
132
 
@@ -92,45 +134,38 @@ buffer_inspect(VALUE self)
92
134
  static VALUE
93
135
  buffer_free(VALUE self)
94
136
  {
95
- Buffer* ptr = BUFFER(self);
96
- if (ptr->parent == Qnil && ptr->storage != NULL) {
97
- free(ptr->storage);
98
- ptr->storage = NULL;
99
- }
100
- return self;
101
- }
137
+ Buffer* ptr;
102
138
 
103
- static void
104
- buffer_release(Buffer* ptr)
105
- {
106
- if (ptr->parent == Qnil && ptr->storage != NULL) {
139
+ Data_Get_Struct(self, Buffer, ptr);
140
+ if (ptr->storage != NULL) {
107
141
  free(ptr->storage);
108
142
  ptr->storage = NULL;
109
143
  }
110
- xfree(ptr);
144
+
145
+ return self;
111
146
  }
112
147
 
113
148
  static void
114
149
  buffer_mark(Buffer* ptr)
115
150
  {
116
- if (ptr->parent != Qnil) {
117
- rb_gc_mark(ptr->parent);
118
- }
151
+ rb_gc_mark(ptr->parent);
119
152
  }
120
153
 
121
154
  void
122
- rb_FFI_Buffer_Init()
155
+ rbffi_Buffer_Init(VALUE moduleFFI)
123
156
  {
124
- VALUE moduleFFI = rb_define_module("FFI");
125
- classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
126
- rb_define_alloc_func(classBuffer, buffer_allocate);
157
+ BufferClass = rb_define_class_under(moduleFFI, "Buffer", rbffi_AbstractMemoryClass);
158
+
159
+ rb_global_variable(&BufferClass);
160
+ rb_define_alloc_func(BufferClass, buffer_allocate);
127
161
 
128
- rb_define_singleton_method(classBuffer, "alloc_inout", buffer_alloc_inout, -1);
129
- rb_define_singleton_method(classBuffer, "alloc_out", buffer_alloc_inout, -1);
130
- rb_define_singleton_method(classBuffer, "alloc_in", buffer_alloc_inout, -1);
162
+ rb_define_singleton_method(BufferClass, "alloc_inout", buffer_alloc_inout, -1);
163
+ rb_define_singleton_method(BufferClass, "alloc_out", buffer_alloc_inout, -1);
164
+ rb_define_singleton_method(BufferClass, "alloc_in", buffer_alloc_inout, -1);
131
165
 
132
- rb_define_method(classBuffer, "initialize", buffer_initialize, -1);
133
- rb_define_method(classBuffer, "inspect", buffer_inspect, 0);
134
- rb_define_method(classBuffer, "+", buffer_plus, 1);
166
+ rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
167
+ rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
168
+ rb_define_method(BufferClass, "type_size", buffer_type_size, 0);
169
+ rb_define_method(BufferClass, "[]", buffer_aref, 1);
170
+ rb_define_method(BufferClass, "+", buffer_plus, 1);
135
171
  }
136
-
data/ext/ffi_c/Callback.c CHANGED
@@ -10,13 +10,13 @@
10
10
  #include "MemoryPointer.h"
11
11
  #include "Callback.h"
12
12
  #include "Types.h"
13
+ #include "Type.h"
13
14
  #include "rbffi.h"
14
15
  #include "compat.h"
15
16
  #include "extconf.h"
16
17
 
17
-
18
- static void CallbackInfo_mark(CallbackInfo *);
19
- static void CallbackInfo_free(CallbackInfo *);
18
+ static void cbinfo_mark(CallbackInfo* cbInfo);
19
+ static void cbinfo_free(CallbackInfo *);
20
20
 
21
21
  #if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
22
22
  static void* ffi_closure_alloc(size_t size, void** code);
@@ -26,36 +26,67 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
26
26
  void* user_data, void* code);
27
27
  #endif /* HAVE_FFI_CLOSURE_ALLOC */
28
28
 
29
- static VALUE classCallbackInfo = Qnil;
30
- static VALUE classNativeCallback = Qnil;
31
- static ID callID = Qnil, cbTableID = Qnil;
29
+ static VALUE CallbackInfoClass = Qnil;
30
+ static VALUE NativeCallbackClass = Qnil;
31
+ static ID id_call = Qnil, id_cbtable = Qnil;
32
+
33
+ VALUE rbffi_CallbackInfoClass = Qnil;
34
+
35
+ static VALUE
36
+ cbinfo_allocate(VALUE klass)
37
+ {
38
+ CallbackInfo* cbInfo;
39
+ VALUE obj = Data_Make_Struct(klass, CallbackInfo, cbinfo_mark, cbinfo_free, cbInfo);
40
+
41
+ cbInfo->type.ffiType = &ffi_type_pointer;
42
+ cbInfo->type.size = ffi_type_pointer.size;
43
+ cbInfo->type.alignment = ffi_type_pointer.alignment;
44
+ cbInfo->type.nativeType = NATIVE_CALLBACK;
45
+ cbInfo->rbReturnType = Qnil;
32
46
 
33
- VALUE rb_FFI_CallbackInfo_class = Qnil;
47
+ return obj;
48
+ }
34
49
 
35
50
  static VALUE
36
- CallbackInfo_new(VALUE klass, VALUE rbReturnType, VALUE rbParamTypes)
51
+ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
37
52
  {
38
53
  CallbackInfo *cbInfo;
39
- VALUE retval;
40
- int paramCount = RARRAY_LEN(rbParamTypes);
54
+ int paramCount;
41
55
  ffi_status status;
42
56
  int i;
43
57
 
44
- retval = Data_Make_Struct(klass, CallbackInfo, CallbackInfo_mark, CallbackInfo_free, cbInfo);
58
+ Check_Type(rbParamTypes, T_ARRAY);
59
+
60
+
61
+ paramCount = RARRAY_LEN(rbParamTypes);
62
+
63
+ Data_Get_Struct(self, CallbackInfo, cbInfo);
45
64
  cbInfo->parameterCount = paramCount;
46
- cbInfo->parameterTypes = xcalloc(paramCount, sizeof(NativeType));
65
+ cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
47
66
  cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
67
+ Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
68
+ cbInfo->rbReturnType = rbReturnType;
69
+ cbInfo->rbParameterTypes = rbParamTypes;
70
+
48
71
  for (i = 0; i < paramCount; ++i) {
49
- cbInfo->parameterTypes[i] = FIX2INT(rb_ary_entry(rbParamTypes, i));
50
- cbInfo->ffiParameterTypes[i] = rb_FFI_NativeTypeToFFI(cbInfo->parameterTypes[i]);
72
+ VALUE entry = rb_ary_entry(rbParamTypes, i);
73
+ if (!rb_obj_is_kind_of(entry, rbffi_TypeClass)) {
74
+ rb_raise(rb_eTypeError, "Invalid parameter type");
75
+ }
76
+ Data_Get_Struct(entry, Type, cbInfo->parameterTypes[i]);
77
+ cbInfo->ffiParameterTypes[i] = cbInfo->parameterTypes[i]->ffiType;
51
78
  if (cbInfo->ffiParameterTypes[i] == NULL) {
52
- rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]);
79
+ rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
53
80
  }
54
81
  }
55
- cbInfo->returnType = FIX2INT(rbReturnType);
56
- cbInfo->ffiReturnType = rb_FFI_NativeTypeToFFI(cbInfo->returnType);
82
+
83
+ if (!rb_obj_is_kind_of(rbReturnType, rbffi_TypeClass)) {
84
+ rb_raise(rb_eTypeError, "Invalid return type");
85
+ }
86
+
87
+ cbInfo->ffiReturnType = cbInfo->returnType->ffiType;
57
88
  if (cbInfo->ffiReturnType == NULL) {
58
- rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
89
+ rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
59
90
  }
60
91
  #if defined(_WIN32) && defined(notyet)
61
92
  cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
@@ -74,38 +105,35 @@ CallbackInfo_new(VALUE klass, VALUE rbReturnType, VALUE rbParamTypes)
74
105
  default:
75
106
  rb_raise(rb_eArgError, "Unknown FFI error");
76
107
  }
77
- return retval;
108
+ return self;
78
109
  }
79
110
 
80
111
  static void
81
- CallbackInfo_mark(CallbackInfo* cbinfo)
112
+ cbinfo_mark(CallbackInfo* cbInfo)
82
113
  {
114
+ rb_gc_mark(cbInfo->rbReturnType);
115
+ rb_gc_mark(cbInfo->rbParameterTypes);
83
116
  }
84
117
 
85
118
  static void
86
- CallbackInfo_free(CallbackInfo* cbInfo)
119
+ cbinfo_free(CallbackInfo* cbInfo)
87
120
  {
88
- if (cbInfo != NULL) {
89
- if (cbInfo->parameterTypes != NULL) {
90
- xfree(cbInfo->parameterTypes);
91
- cbInfo->parameterTypes = NULL;
92
- }
93
- if (cbInfo->ffiParameterTypes != NULL) {
94
- xfree(cbInfo->ffiParameterTypes);
95
- cbInfo->ffiParameterTypes = NULL;
96
- }
97
- xfree(cbInfo);
121
+ if (cbInfo->parameterTypes != NULL) {
122
+ xfree(cbInfo->parameterTypes);
98
123
  }
124
+ if (cbInfo->ffiParameterTypes != NULL) {
125
+ xfree(cbInfo->ffiParameterTypes);
126
+ }
127
+ xfree(cbInfo);
99
128
  }
100
129
 
101
130
  static void
102
131
  native_callback_free(NativeCallback* cb)
103
132
  {
104
- if (cb != NULL) {
105
- if (cb->ffi_closure != NULL) {
106
- ffi_closure_free(cb->ffi_closure);
107
- }
133
+ if (cb->ffi_closure != NULL) {
134
+ ffi_closure_free(cb->ffi_closure);
108
135
  }
136
+ xfree(cb);
109
137
  }
110
138
 
111
139
  static void
@@ -127,7 +155,7 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
127
155
  rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
128
156
  for (i = 0; i < cbInfo->parameterCount; ++i) {
129
157
  VALUE param;
130
- switch (cbInfo->parameterTypes[i]) {
158
+ switch (cbInfo->parameterTypes[i]->nativeType) {
131
159
  case NATIVE_INT8:
132
160
  param = INT2NUM(*(int8_t *) parameters[i]);
133
161
  break;
@@ -162,7 +190,14 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
162
190
  param = rb_tainted_str_new2(*(char **) parameters[i]);
163
191
  break;
164
192
  case NATIVE_POINTER:
165
- param = rb_FFI_Pointer_new(*(void **) parameters[i]);
193
+ param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
194
+ break;
195
+ case NATIVE_BOOL:
196
+ param = (*(void **) parameters[i]) ? Qtrue : Qfalse;
197
+ break;
198
+ case NATIVE_CALLBACK:
199
+ param = rbffi_NativeValue_ToRuby(cbInfo->parameterTypes[i],
200
+ rb_ary_entry(cbInfo->rbParameterTypes, i), parameters[i], Qnil);
166
201
  break;
167
202
  default:
168
203
  param = Qnil;
@@ -170,10 +205,10 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
170
205
  }
171
206
  rbParams[i] = param;
172
207
  }
173
- rbReturnValue = rb_funcall2(cb->rbProc, callID, cbInfo->parameterCount, rbParams);
208
+ rbReturnValue = rb_funcall2(cb->rbProc, id_call, cbInfo->parameterCount, rbParams);
174
209
  if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
175
210
  memset(retval, 0, cbInfo->ffiReturnType->size);
176
- } else switch (cbInfo->returnType) {
211
+ } else switch (cbInfo->returnType->nativeType) {
177
212
  case NATIVE_INT8:
178
213
  case NATIVE_INT16:
179
214
  case NATIVE_INT32:
@@ -197,58 +232,89 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
197
232
  *((double *) retval) = NUM2DBL(rbReturnValue);
198
233
  break;
199
234
  case NATIVE_POINTER:
200
- if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rb_FFI_Pointer_class)) {
235
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
201
236
  *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
202
237
  } else {
203
238
  // Default to returning NULL if not a value pointer object. handles nil case as well
204
239
  *((void **) retval) = NULL;
205
240
  }
206
241
  break;
242
+ case NATIVE_BOOL:
243
+ *((ffi_sarg *) retval) = TYPE(rbReturnValue) == T_TRUE ? 1 : 0;
244
+ break;
245
+ case NATIVE_CALLBACK:
246
+ if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
247
+ VALUE callback;
248
+
249
+ callback = rbffi_NativeCallback_ForProc(rbReturnValue, cbInfo->rbReturnType);
250
+
251
+ *((void **) retval) = ((NativeCallback *) DATA_PTR(callback))->code;
252
+ } else {
253
+ *((void **) retval) = NULL;
254
+ }
255
+ break;
256
+
207
257
  default:
258
+ *((ffi_arg *) retval) = 0;
208
259
  break;
209
260
  }
210
261
  }
211
262
 
263
+ static VALUE
264
+ native_callback_allocate(VALUE klass)
265
+ {
266
+ NativeCallback* closure;
267
+ VALUE obj;
268
+
269
+ obj = Data_Make_Struct(klass, NativeCallback, native_callback_mark, native_callback_free, closure);
270
+ closure->rbCallbackInfo = Qnil;
271
+ closure->rbProc = Qnil;
272
+
273
+ return obj;
274
+ }
275
+
212
276
  VALUE
213
- rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
277
+ rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
214
278
  {
215
279
  NativeCallback* closure = NULL;
216
- CallbackInfo* cbInfo = (CallbackInfo *) DATA_PTR(rbCallbackInfo);
280
+ CallbackInfo* cbInfo;
281
+ VALUE obj;
217
282
  ffi_status status;
218
-
219
- closure = ALLOC(NativeCallback);
283
+
284
+ Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
285
+ obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
286
+ closure->cbInfo = cbInfo;
287
+ closure->rbProc = rbProc;
288
+ closure->rbCallbackInfo = rbCallbackInfo;
289
+
220
290
  closure->ffi_closure = ffi_closure_alloc(sizeof(*closure->ffi_closure), &closure->code);
221
291
  if (closure->ffi_closure == NULL) {
222
- xfree(closure);
223
292
  rb_raise(rb_eNoMemError, "Failed to allocate FFI native closure");
224
293
  }
225
- closure->cbInfo = cbInfo;
226
- closure->rbProc = rbProc;
227
- closure->rbCallbackInfo = rbCallbackInfo;
294
+
228
295
  status = ffi_prep_closure_loc(closure->ffi_closure, &cbInfo->ffi_cif,
229
296
  native_callback_invoke, closure, closure->code);
230
297
  if (status != FFI_OK) {
231
- ffi_closure_free(closure->ffi_closure);
232
- xfree(closure);
233
298
  rb_raise(rb_eArgError, "ffi_prep_closure_loc failed");
234
299
  }
235
- return Data_Wrap_Struct(classNativeCallback, native_callback_mark, native_callback_free, closure);
300
+
301
+ return obj;
236
302
  }
237
303
 
238
304
  VALUE
239
- rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo)
305
+ rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
240
306
  {
241
307
  VALUE callback;
242
- VALUE cbTable = RTEST(rb_ivar_defined(proc, cbTableID)) ? rb_ivar_get(proc, cbTableID) : Qnil;
308
+ VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
243
309
  if (cbTable == Qnil) {
244
310
  cbTable = rb_hash_new();
245
- rb_ivar_set(proc, cbTableID, cbTable);
311
+ rb_ivar_set(proc, id_cbtable, cbTable);
246
312
  }
247
313
  callback = rb_hash_aref(cbTable, cbInfo);
248
314
  if (callback != Qnil) {
249
315
  return callback;
250
316
  }
251
- callback = rb_FFI_NativeCallback_new(cbInfo, proc);
317
+ callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
252
318
  rb_hash_aset(cbTable, cbInfo, callback);
253
319
  return callback;
254
320
  }
@@ -292,12 +358,17 @@ ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
292
358
  #endif /* HAVE_FFI_CLOSURE_ALLOC */
293
359
 
294
360
  void
295
- rb_FFI_Callback_Init()
361
+ rbffi_Callback_Init(VALUE moduleFFI)
296
362
  {
297
- VALUE moduleFFI = rb_define_module("FFI");
298
- rb_FFI_CallbackInfo_class = classCallbackInfo = rb_define_class_under(moduleFFI, "CallbackInfo", rb_cObject);
299
- rb_define_singleton_method(classCallbackInfo, "new", CallbackInfo_new, 2);
300
- classNativeCallback = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
301
- callID = rb_intern("call");
302
- cbTableID = rb_intern("@__ffi_callback_table__");
363
+ rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
364
+ rb_global_variable(&rbffi_CallbackInfoClass);
365
+
366
+ rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
367
+ rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
368
+
369
+ NativeCallbackClass = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
370
+ rb_global_variable(&NativeCallbackClass);
371
+ rb_define_alloc_func(NativeCallbackClass, native_callback_allocate);
372
+ id_call = rb_intern("call");
373
+ id_cbtable = rb_intern("@__ffi_callback_table__");
303
374
  }
data/ext/ffi_c/Callback.h CHANGED
@@ -2,6 +2,7 @@
2
2
  #define _CALLBACK_H
3
3
 
4
4
  #include "Types.h"
5
+ #include "Type.h"
5
6
 
6
7
  #ifdef __cplusplus
7
8
  extern "C" {
@@ -9,8 +10,12 @@ extern "C" {
9
10
  #include <ffi.h>
10
11
 
11
12
  typedef struct {
12
- NativeType returnType;
13
- NativeType* parameterTypes;
13
+ Type type; // The native type of a CallbackInfo object
14
+ VALUE rbReturnType;
15
+ VALUE rbParameterTypes;
16
+
17
+ Type* returnType;
18
+ Type** parameterTypes;
14
19
  ffi_type* ffiReturnType;
15
20
  ffi_type** ffiParameterTypes;
16
21
  ffi_cif ffi_cif;
@@ -29,9 +34,10 @@ typedef struct {
29
34
  VALUE rbProc;
30
35
  } NativeCallback;
31
36
 
32
- extern VALUE rb_FFI_CallbackInfo_class;
33
- extern VALUE rb_FFI_NativeCallback_new(VALUE, VALUE);
34
- extern VALUE rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo);
37
+ extern VALUE rbffi_CallbackInfoClass;
38
+ extern void rbffi_Callback_Init(VALUE ffiModule);
39
+ extern VALUE rbffi_NativeCallback_NewInstance(VALUE, VALUE);
40
+ extern VALUE rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo);
35
41
 
36
42
  #ifdef __cplusplus
37
43
  }