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
@@ -17,7 +17,7 @@ static void autoptr_mark(AutoPointer* ptr);
17
17
  static VALUE autoptr_allocate(VALUE klass);
18
18
  static VALUE autoptr_set_parent(VALUE self, VALUE parent);
19
19
 
20
- VALUE rb_FFI_AutoPointer_class = Qnil;
20
+ VALUE rbffi_AutoPointerClass = Qnil;
21
21
 
22
22
  static VALUE
23
23
  autoptr_allocate(VALUE klass)
@@ -25,7 +25,7 @@ autoptr_allocate(VALUE klass)
25
25
  AutoPointer* p;
26
26
  VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, -1, p);
27
27
  p->parent = Qnil;
28
- p->memory.ops = &rb_FFI_AbstractMemory_ops;
28
+ p->memory.ops = &rbffi_AbstractMemoryOps;
29
29
 
30
30
  return obj;
31
31
  }
@@ -34,7 +34,7 @@ static VALUE
34
34
  autoptr_set_parent(VALUE self, VALUE parent)
35
35
  {
36
36
  AutoPointer* p;
37
- AbstractMemory* ptr = rb_FFI_AbstractMemory_cast(parent, rb_FFI_Pointer_class);
37
+ AbstractMemory* ptr = rbffi_AbstractMemory_Cast(parent, rbffi_PointerClass);
38
38
 
39
39
  Data_Get_Struct(self, AutoPointer, p);
40
40
  p->memory = *ptr;
@@ -50,12 +50,11 @@ autoptr_mark(AutoPointer* ptr)
50
50
  }
51
51
 
52
52
  void
53
- rb_FFI_AutoPointer_Init()
53
+ rbffi_AutoPointer_Init(VALUE moduleFFI)
54
54
  {
55
- VALUE moduleFFI = rb_define_module("FFI");
56
- rb_FFI_AutoPointer_class = rb_define_class_under(moduleFFI, "AutoPointer", rb_FFI_Pointer_class);
57
- rb_global_variable(&rb_FFI_AutoPointer_class);
55
+ rbffi_AutoPointerClass = rb_define_class_under(moduleFFI, "AutoPointer", rbffi_PointerClass);
56
+ rb_global_variable(&rbffi_AutoPointerClass);
58
57
 
59
- rb_define_alloc_func(rb_FFI_AutoPointer_class, autoptr_allocate);
60
- rb_define_protected_method(rb_FFI_AutoPointer_class, "parent=", autoptr_set_parent, 1);
58
+ rb_define_alloc_func(rbffi_AutoPointerClass, autoptr_allocate);
59
+ rb_define_protected_method(rbffi_AutoPointerClass, "parent=", autoptr_set_parent, 1);
61
60
  }
@@ -6,8 +6,8 @@
6
6
  extern "C" {
7
7
  #endif
8
8
 
9
- extern void rb_FFI_AutoPointer_Init(void);
10
- extern VALUE rb_FFI_AutoPointer_class;
9
+ extern void rbffi_AutoPointer_Init(VALUE ffiModule);
10
+ extern VALUE rbffi_AutoPointerClass;
11
11
 
12
12
 
13
13
  #ifdef __cplusplus
@@ -18,8 +18,8 @@ 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)
@@ -29,7 +29,7 @@ buffer_allocate(VALUE klass)
29
29
 
30
30
  obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
31
31
  buffer->parent = Qnil;
32
- buffer->memory.ops = &rb_FFI_AbstractMemory_ops;
32
+ buffer->memory.ops = &rbffi_AbstractMemoryOps;
33
33
 
34
34
  return obj;
35
35
  }
@@ -55,7 +55,7 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
55
55
  Data_Get_Struct(self, Buffer, p);
56
56
 
57
57
  nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
58
- p->type_size = rb_FFI_type_size(size);
58
+ p->type_size = rbffi_type_size(size);
59
59
  p->memory.size = p->type_size * (nargs > 1 ? NUM2LONG(count) : 1);
60
60
 
61
61
  p->storage = malloc(p->memory.size + 7);
@@ -66,7 +66,7 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
66
66
  /* ensure the memory is aligned on at least a 8 byte boundary */
67
67
  p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
68
68
 
69
- if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
69
+ if (nargs > 2 && (RTEST(clear) || clear == Qnil) && p->memory.size > 0) {
70
70
  memset(p->memory.address, 0, p->memory.size);
71
71
  }
72
72
 
@@ -93,10 +93,10 @@ buffer_plus(VALUE self, VALUE offset)
93
93
 
94
94
  checkBounds(&ptr->memory, off, 1);
95
95
 
96
- retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, -1, p);
96
+ retval = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, p);
97
97
  p->memory.address = ptr->memory.address + off;
98
98
  p->memory.size = ptr->memory.size - off;
99
- p->memory.ops = &rb_FFI_AbstractMemory_ops;
99
+ p->memory.ops = &rbffi_AbstractMemoryOps;
100
100
  p->parent = self;
101
101
 
102
102
  return retval;
@@ -152,21 +152,20 @@ buffer_mark(Buffer* ptr)
152
152
  }
153
153
 
154
154
  void
155
- rb_FFI_Buffer_Init()
155
+ rbffi_Buffer_Init(VALUE moduleFFI)
156
156
  {
157
- VALUE moduleFFI = rb_define_module("FFI");
158
- classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
157
+ BufferClass = rb_define_class_under(moduleFFI, "Buffer", rbffi_AbstractMemoryClass);
159
158
 
160
- rb_global_variable(&classBuffer);
161
- rb_define_alloc_func(classBuffer, buffer_allocate);
159
+ rb_global_variable(&BufferClass);
160
+ rb_define_alloc_func(BufferClass, buffer_allocate);
162
161
 
163
- rb_define_singleton_method(classBuffer, "alloc_inout", buffer_alloc_inout, -1);
164
- rb_define_singleton_method(classBuffer, "alloc_out", buffer_alloc_inout, -1);
165
- 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);
166
165
 
167
- rb_define_method(classBuffer, "initialize", buffer_initialize, -1);
168
- rb_define_method(classBuffer, "inspect", buffer_inspect, 0);
169
- rb_define_method(classBuffer, "type_size", buffer_type_size, 0);
170
- rb_define_method(classBuffer, "[]", buffer_aref, 1);
171
- 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);
172
171
  }
@@ -10,11 +10,12 @@
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 cbinfo_mark(CallbackInfo* cbInfo);
18
19
  static void cbinfo_free(CallbackInfo *);
19
20
 
20
21
  #if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
@@ -25,17 +26,25 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
25
26
  void* user_data, void* code);
26
27
  #endif /* HAVE_FFI_CLOSURE_ALLOC */
27
28
 
28
- static VALUE classCallbackInfo = Qnil;
29
- static VALUE classNativeCallback = Qnil;
30
- 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;
31
32
 
32
- VALUE rb_FFI_CallbackInfo_class = Qnil;
33
+ VALUE rbffi_CallbackInfoClass = Qnil;
33
34
 
34
35
  static VALUE
35
36
  cbinfo_allocate(VALUE klass)
36
37
  {
37
38
  CallbackInfo* cbInfo;
38
- return Data_Make_Struct(klass, CallbackInfo, NULL, cbinfo_free, 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;
46
+
47
+ return obj;
39
48
  }
40
49
 
41
50
  static VALUE
@@ -47,25 +56,37 @@ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
47
56
  int i;
48
57
 
49
58
  Check_Type(rbParamTypes, T_ARRAY);
59
+
60
+
50
61
  paramCount = RARRAY_LEN(rbParamTypes);
51
62
 
52
63
  Data_Get_Struct(self, CallbackInfo, cbInfo);
53
64
  cbInfo->parameterCount = paramCount;
54
- cbInfo->parameterTypes = xcalloc(paramCount, sizeof(NativeType));
65
+ cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
55
66
  cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
56
- cbInfo->returnType = FIX2INT(rbReturnType);
67
+ Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
68
+ cbInfo->rbReturnType = rbReturnType;
69
+ cbInfo->rbParameterTypes = rbParamTypes;
57
70
 
58
71
  for (i = 0; i < paramCount; ++i) {
59
- cbInfo->parameterTypes[i] = FIX2INT(rb_ary_entry(rbParamTypes, i));
60
- 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;
61
78
  if (cbInfo->ffiParameterTypes[i] == NULL) {
62
- rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]);
79
+ rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
63
80
  }
64
81
  }
65
82
 
66
- cbInfo->ffiReturnType = rb_FFI_NativeTypeToFFI(cbInfo->returnType);
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;
67
88
  if (cbInfo->ffiReturnType == NULL) {
68
- rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
89
+ rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
69
90
  }
70
91
  #if defined(_WIN32) && defined(notyet)
71
92
  cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
@@ -87,6 +108,13 @@ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
87
108
  return self;
88
109
  }
89
110
 
111
+ static void
112
+ cbinfo_mark(CallbackInfo* cbInfo)
113
+ {
114
+ rb_gc_mark(cbInfo->rbReturnType);
115
+ rb_gc_mark(cbInfo->rbParameterTypes);
116
+ }
117
+
90
118
  static void
91
119
  cbinfo_free(CallbackInfo* cbInfo)
92
120
  {
@@ -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,14 +232,30 @@ 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
  }
@@ -223,7 +274,7 @@ native_callback_allocate(VALUE klass)
223
274
  }
224
275
 
225
276
  VALUE
226
- rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
277
+ rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
227
278
  {
228
279
  NativeCallback* closure = NULL;
229
280
  CallbackInfo* cbInfo;
@@ -231,7 +282,7 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
231
282
  ffi_status status;
232
283
 
233
284
  Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
234
- obj = Data_Make_Struct(classNativeCallback, NativeCallback, native_callback_mark, native_callback_free, closure);
285
+ obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
235
286
  closure->cbInfo = cbInfo;
236
287
  closure->rbProc = rbProc;
237
288
  closure->rbCallbackInfo = rbCallbackInfo;
@@ -251,19 +302,19 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
251
302
  }
252
303
 
253
304
  VALUE
254
- rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo)
305
+ rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
255
306
  {
256
307
  VALUE callback;
257
- 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;
258
309
  if (cbTable == Qnil) {
259
310
  cbTable = rb_hash_new();
260
- rb_ivar_set(proc, cbTableID, cbTable);
311
+ rb_ivar_set(proc, id_cbtable, cbTable);
261
312
  }
262
313
  callback = rb_hash_aref(cbTable, cbInfo);
263
314
  if (callback != Qnil) {
264
315
  return callback;
265
316
  }
266
- callback = rb_FFI_NativeCallback_new(cbInfo, proc);
317
+ callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
267
318
  rb_hash_aset(cbTable, cbInfo, callback);
268
319
  return callback;
269
320
  }
@@ -307,16 +358,17 @@ ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
307
358
  #endif /* HAVE_FFI_CLOSURE_ALLOC */
308
359
 
309
360
  void
310
- rb_FFI_Callback_Init()
361
+ rbffi_Callback_Init(VALUE moduleFFI)
311
362
  {
312
- VALUE moduleFFI = rb_define_module("FFI");
363
+ rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
364
+ rb_global_variable(&rbffi_CallbackInfoClass);
313
365
 
314
- rb_FFI_CallbackInfo_class = classCallbackInfo = rb_define_class_under(moduleFFI, "CallbackInfo", rb_cObject);
315
- rb_define_alloc_func(classCallbackInfo, cbinfo_allocate);
316
- rb_define_method(classCallbackInfo, "initialize", cbinfo_initialize, 2);
366
+ rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
367
+ rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
317
368
 
318
- classNativeCallback = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
319
- rb_define_alloc_func(classNativeCallback, native_callback_allocate);
320
- callID = rb_intern("call");
321
- cbTableID = rb_intern("@__ffi_callback_table__");
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__");
322
374
  }
@@ -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
  }
@@ -12,12 +12,25 @@
12
12
 
13
13
  #include "rbffi.h"
14
14
  #include "compat.h"
15
+ #include "AbstractMemory.h"
15
16
  #include "Pointer.h"
16
- #include "NativeLibrary.h"
17
+ #include "DynamicLibrary.h"
18
+
19
+ typedef struct LibrarySymbol_ {
20
+ AbstractMemory memory;
21
+ VALUE library;
22
+ VALUE name;
23
+ } LibrarySymbol;
17
24
 
18
25
  static VALUE library_initialize(VALUE self, VALUE libname, VALUE libflags);
19
26
  static void library_free(Library* lib);
20
- static VALUE classLibrary;
27
+
28
+
29
+ static VALUE symbol_allocate(VALUE klass);
30
+ static VALUE symbol_new(VALUE library, void* address, VALUE name);
31
+ static void symbol_mark(LibrarySymbol* sym);
32
+
33
+ static VALUE LibraryClass = Qnil, SymbolClass = Qnil;
21
34
 
22
35
  #if defined(_WIN32) || defined(__WIN32__)
23
36
  static void* dl_open(const char* name, int flags);
@@ -80,7 +93,8 @@ library_dlsym(VALUE self, VALUE name)
80
93
 
81
94
  Data_Get_Struct(self, Library, library);
82
95
  address = dl_sym(library->handle, StringValueCStr(name));
83
- return address != NULL ? rb_FFI_Pointer_new(address) : Qnil;
96
+
97
+ return address != NULL ? symbol_new(self, address, name) : Qnil;
84
98
  }
85
99
 
86
100
  static VALUE
@@ -122,21 +136,74 @@ dl_error(char* buf, int size)
122
136
  }
123
137
  #endif
124
138
 
139
+ static VALUE
140
+ symbol_allocate(VALUE klass)
141
+ {
142
+ LibrarySymbol* sym;
143
+ VALUE obj = Data_Make_Struct(klass, LibrarySymbol, NULL, -1, sym);
144
+ sym->name = Qnil;
145
+ sym->library = Qnil;
146
+
147
+ return obj;
148
+ }
149
+
150
+ static VALUE
151
+ symbol_new(VALUE library, void* address, VALUE name)
152
+ {
153
+ LibrarySymbol* sym;
154
+ VALUE obj = Data_Make_Struct(SymbolClass, LibrarySymbol, symbol_mark, -1, sym);
155
+
156
+ sym->memory.address = address;
157
+ sym->memory.size = LONG_MAX;
158
+ sym->library = library;
159
+ sym->name = name;
160
+
161
+ return obj;
162
+ }
163
+
164
+ static void
165
+ symbol_mark(LibrarySymbol* sym)
166
+ {
167
+ rb_gc_mark(sym->library);
168
+ rb_gc_mark(sym->name);
169
+ }
170
+
171
+ static VALUE
172
+ symbol_inspect(VALUE self)
173
+ {
174
+ LibrarySymbol* sym;
175
+ char buf[256];
176
+
177
+ Data_Get_Struct(self, LibrarySymbol, sym);
178
+ snprintf(buf, sizeof(buf), "#<FFI::Library::Symbol name=%s address=%p>",
179
+ StringValueCStr(sym->name), sym->memory.address);
180
+ return rb_str_new2(buf);
181
+ }
182
+
125
183
  void
126
- rb_FFI_NativeLibrary_Init()
184
+ rbffi_DynamicLibrary_Init(VALUE moduleFFI)
127
185
  {
128
- VALUE moduleFFI = rb_define_module("FFI");
129
- classLibrary = rb_define_class_under(moduleFFI, "DynamicLibrary", rb_cObject);
130
- rb_define_const(moduleFFI, "NativeLibrary", classLibrary); // backwards compat library
131
- rb_define_alloc_func(classLibrary, library_allocate);
132
- rb_define_singleton_method(classLibrary, "open", library_open, 2);
133
- rb_define_singleton_method(classLibrary, "last_error", library_dlerror, 0);
134
- rb_define_method(classLibrary, "initialize", library_initialize, 2);
135
- rb_define_method(classLibrary, "find_symbol", library_dlsym, 1);
136
- rb_define_method(classLibrary, "last_error", library_dlerror, 0);
137
- rb_define_attr(classLibrary, "name", 1, 0);
138
-
139
- #define DEF(x) rb_define_const(classLibrary, "RTLD_" #x, UINT2NUM(RTLD_##x))
186
+ LibraryClass = rb_define_class_under(moduleFFI, "DynamicLibrary", rb_cObject);
187
+ rb_global_variable(&LibraryClass);
188
+ SymbolClass = rb_define_class_under(LibraryClass, "Symbol", rbffi_PointerClass);
189
+ rb_global_variable(&SymbolClass);
190
+
191
+ rb_define_const(moduleFFI, "NativeLibrary", LibraryClass); // backwards compat library
192
+ rb_define_alloc_func(LibraryClass, library_allocate);
193
+ rb_define_singleton_method(LibraryClass, "open", library_open, 2);
194
+ rb_define_singleton_method(LibraryClass, "last_error", library_dlerror, 0);
195
+ rb_define_method(LibraryClass, "initialize", library_initialize, 2);
196
+ rb_define_method(LibraryClass, "find_symbol", library_dlsym, 1);
197
+ rb_define_method(LibraryClass, "find_function", library_dlsym, 1);
198
+ rb_define_method(LibraryClass, "find_variable", library_dlsym, 1);
199
+ rb_define_method(LibraryClass, "last_error", library_dlerror, 0);
200
+ rb_define_attr(LibraryClass, "name", 1, 0);
201
+
202
+ rb_define_alloc_func(SymbolClass, symbol_allocate);
203
+ rb_undef_method(SymbolClass, "new");
204
+ rb_define_method(SymbolClass, "inspect", symbol_inspect, 0);
205
+
206
+ #define DEF(x) rb_define_const(LibraryClass, "RTLD_" #x, UINT2NUM(RTLD_##x))
140
207
  DEF(LAZY);
141
208
  DEF(NOW);
142
209
  DEF(GLOBAL);