ffi 0.6.0 → 1.0.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/History.txt +109 -0
  2. data/LICENSE +10 -21
  3. data/README.rdoc +1 -0
  4. data/Rakefile +3 -2
  5. data/ext/ffi_c/AbstractMemory.c +56 -38
  6. data/ext/ffi_c/AbstractMemory.h +15 -22
  7. data/ext/ffi_c/Buffer.c +61 -22
  8. data/ext/ffi_c/Call.c +55 -543
  9. data/ext/ffi_c/Call.h +1 -1
  10. data/ext/ffi_c/DataConverter.c +62 -0
  11. data/ext/ffi_c/DynamicLibrary.c +21 -1
  12. data/ext/ffi_c/Function.c +255 -32
  13. data/ext/ffi_c/MappedType.c +146 -0
  14. data/ext/ffi_c/MappedType.h +57 -0
  15. data/ext/ffi_c/MemoryPointer.c +12 -33
  16. data/ext/ffi_c/Platform.c +2 -0
  17. data/ext/ffi_c/Pointer.c +66 -28
  18. data/ext/ffi_c/Struct.c +106 -318
  19. data/ext/ffi_c/Struct.h +6 -0
  20. data/ext/ffi_c/StructByReference.c +150 -0
  21. data/ext/ffi_c/StructByReference.h +50 -0
  22. data/ext/ffi_c/StructLayout.c +25 -14
  23. data/ext/ffi_c/Type.c +39 -68
  24. data/ext/ffi_c/Type.h +12 -22
  25. data/ext/ffi_c/Types.c +21 -6
  26. data/ext/ffi_c/Types.h +7 -7
  27. data/ext/ffi_c/Variadic.c +21 -17
  28. data/ext/ffi_c/extconf.rb +4 -0
  29. data/ext/ffi_c/ffi.c +8 -2
  30. data/ext/ffi_c/libffi/configure +1 -1
  31. data/ext/ffi_c/libffi.gnu.mk +1 -1
  32. data/ext/ffi_c/libffi.mk +1 -1
  33. data/ext/ffi_c/rbffi.h +1 -0
  34. data/gen/Rakefile +4 -2
  35. data/lib/ffi/autopointer.rb +23 -22
  36. data/lib/ffi/enum.rb +36 -21
  37. data/lib/ffi/errno.rb +20 -0
  38. data/lib/ffi/ffi.rb +13 -79
  39. data/lib/ffi/io.rb +12 -20
  40. data/lib/ffi/library.rb +110 -93
  41. data/lib/ffi/managedstruct.rb +1 -1
  42. data/lib/ffi/memorypointer.rb +15 -21
  43. data/lib/ffi/platform.rb +24 -28
  44. data/lib/ffi/pointer.rb +14 -21
  45. data/lib/ffi/struct.rb +100 -51
  46. data/lib/ffi/struct_layout_builder.rb +158 -0
  47. data/lib/ffi/types.rb +99 -128
  48. data/lib/ffi/union.rb +20 -0
  49. data/lib/ffi/variadic.rb +33 -22
  50. data/spec/ffi/async_callback_spec.rb +23 -0
  51. data/spec/ffi/callback_spec.rb +62 -0
  52. data/spec/ffi/custom_param_type.rb +31 -0
  53. data/spec/ffi/custom_type_spec.rb +73 -0
  54. data/spec/ffi/enum_spec.rb +19 -0
  55. data/spec/ffi/ffi_spec.rb +24 -0
  56. data/spec/ffi/pointer_spec.rb +15 -0
  57. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
  58. data/spec/ffi/strptr_spec.rb +36 -0
  59. data/spec/ffi/struct_packed_spec.rb +46 -0
  60. data/spec/ffi/struct_spec.rb +39 -7
  61. data/spec/ffi/typedef_spec.rb +14 -0
  62. data/tasks/ann.rake +80 -0
  63. data/tasks/extension.rake +25 -0
  64. data/tasks/gem.rake +200 -0
  65. data/tasks/git.rake +41 -0
  66. data/tasks/notes.rake +27 -0
  67. data/tasks/post_load.rake +34 -0
  68. data/tasks/rdoc.rake +50 -0
  69. data/tasks/rubyforge.rake +55 -0
  70. data/tasks/setup.rb +301 -0
  71. data/tasks/spec.rake +54 -0
  72. data/tasks/svn.rake +47 -0
  73. data/tasks/test.rake +40 -0
  74. metadata +64 -11
  75. data/ext/ffi_c/AutoPointer.c +0 -60
  76. data/ext/ffi_c/AutoPointer.h +0 -18
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Copyright (c) 2009, Wayne Meissner
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * * Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright notice
11
+ * this list of conditions and the following disclaimer in the documentation
12
+ * and/or other materials provided with the distribution.
13
+ * * The name of the author or authors may not be used to endorse or promote
14
+ * products derived from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ */
27
+
28
+ #ifndef RBFFI_STRUCTBYREFERENCE_H
29
+ #define RBFFI_STRUCTBYREFERENCE_H
30
+
31
+ #include <ruby.h>
32
+
33
+ #ifdef __cplusplus
34
+ extern "C" {
35
+ #endif
36
+
37
+ typedef struct StructByReference_ {
38
+ VALUE rbStructClass;
39
+ } StructByReference;
40
+
41
+ void rbffi_StructByReference_Init(VALUE moduleFFI);
42
+
43
+ extern VALUE rbffi_StructByReferenceClass;
44
+
45
+ #ifdef __cplusplus
46
+ }
47
+ #endif
48
+
49
+ #endif /* RBFFI_STRUCTBYREFERENCE_H */
50
+
@@ -52,6 +52,8 @@ static void struct_layout_free(StructLayout *);
52
52
  static void struct_field_mark(StructField* );
53
53
 
54
54
  VALUE rbffi_StructLayoutFieldClass = Qnil;
55
+ VALUE rbffi_StructLayoutNumberFieldClass = Qnil, rbffi_StructLayoutPointerFieldClass = Qnil;
56
+ VALUE rbffi_StructLayoutStringFieldClass = Qnil;
55
57
  VALUE rbffi_StructLayoutFunctionFieldClass = Qnil, rbffi_StructLayoutArrayFieldClass = Qnil;
56
58
 
57
59
  VALUE rbffi_StructLayoutClass = Qnil;
@@ -320,6 +322,7 @@ struct_layout_allocate(VALUE klass)
320
322
  layout->rbFieldMap = Qnil;
321
323
  layout->rbFieldNames = Qnil;
322
324
  layout->rbFields = Qnil;
325
+ layout->fieldSymbolTable = st_init_numtable();
323
326
  layout->base.ffiType = xcalloc(1, sizeof(*layout->base.ffiType));
324
327
  layout->base.ffiType->size = 0;
325
328
  layout->base.ffiType->alignment = 0;
@@ -329,29 +332,29 @@ struct_layout_allocate(VALUE klass)
329
332
  }
330
333
 
331
334
  static VALUE
332
- struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size, VALUE align)
335
+ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
333
336
  {
334
337
  StructLayout* layout;
335
338
  ffi_type* ltype;
336
339
  int i;
337
340
 
338
341
  Data_Get_Struct(self, StructLayout, layout);
342
+ layout->fieldCount = RARRAY_LEN(fields);
339
343
  layout->rbFieldMap = rb_hash_new();
340
- layout->rbFieldNames = rb_ary_dup(field_names);
344
+ layout->rbFieldNames = rb_ary_new2(layout->fieldCount);
341
345
  layout->size = NUM2INT(size);
342
346
  layout->align = NUM2INT(align);
343
- layout->fieldCount = RARRAY_LEN(field_names);
344
347
  layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
345
348
  layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
346
349
  layout->rbFields = rb_ary_new2(layout->fieldCount);
347
350
  layout->base.ffiType->elements = layout->ffiTypes;
348
- layout->base.ffiType->size = 0;
349
- layout->base.ffiType->alignment = 1;
351
+ layout->base.ffiType->size = layout->size;
352
+ layout->base.ffiType->alignment = layout->align;
350
353
 
351
354
  ltype = layout->base.ffiType;
352
355
  for (i = 0; i < (int) layout->fieldCount; ++i) {
353
- VALUE rbName = rb_ary_entry(field_names, i);
354
- VALUE rbField = rb_hash_aref(fields, rbName);
356
+ VALUE rbField = rb_ary_entry(fields, i);
357
+ VALUE rbName;
355
358
  StructField* field;
356
359
  ffi_type* ftype;
357
360
 
@@ -359,6 +362,7 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
359
362
  if (!rb_obj_is_kind_of(rbField, rbffi_StructLayoutFieldClass)) {
360
363
  rb_raise(rb_eTypeError, "wrong type for field %d.", i);
361
364
  }
365
+ rbName = rb_funcall2(rbField, rb_intern("name"), 0, NULL);
362
366
 
363
367
  Data_Get_Struct(rbField, StructField, field = layout->fields[i]);
364
368
 
@@ -371,20 +375,17 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
371
375
  rb_raise(rb_eTypeError, "type of field %d has zero size", i);
372
376
  }
373
377
 
374
- rb_hash_aset(layout->rbFieldMap, rbName, rbField);
375
378
  layout->ffiTypes[i] = ftype;
379
+ st_insert(layout->fieldSymbolTable, rbName, rbField);
380
+ rb_hash_aset(layout->rbFieldMap, rbName, rbField);
376
381
  rb_ary_push(layout->rbFields, rbField);
377
- ltype->size = MAX(ltype->size, field->offset + ftype->size);
378
- ltype->alignment = MAX(ltype->alignment, ftype->alignment);
382
+ rb_ary_push(layout->rbFieldNames, rbName);
379
383
  }
380
384
 
381
385
  if (ltype->size == 0) {
382
386
  rb_raise(rb_eRuntimeError, "Struct size is zero");
383
387
  }
384
388
 
385
- // Include tail padding
386
- ltype->size = FFI_ALIGN(ltype->size, ltype->alignment);
387
-
388
389
  return self;
389
390
  }
390
391
 
@@ -442,6 +443,7 @@ struct_layout_free(StructLayout *layout)
442
443
  xfree(layout->ffiTypes);
443
444
  xfree(layout->base.ffiType);
444
445
  xfree(layout->fields);
446
+ st_free_table(layout->fieldSymbolTable);
445
447
  xfree(layout);
446
448
  }
447
449
 
@@ -455,6 +457,15 @@ rbffi_StructLayout_Init(VALUE moduleFFI)
455
457
  rbffi_StructLayoutFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Field", rb_cObject);
456
458
  rb_global_variable(&rbffi_StructLayoutFieldClass);
457
459
 
460
+ rbffi_StructLayoutNumberFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Number", rbffi_StructLayoutFieldClass);
461
+ rb_global_variable(&rbffi_StructLayoutNumberFieldClass);
462
+
463
+ rbffi_StructLayoutStringFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "String", rbffi_StructLayoutFieldClass);
464
+ rb_global_variable(&rbffi_StructLayoutStringFieldClass);
465
+
466
+ rbffi_StructLayoutPointerFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Pointer", rbffi_StructLayoutFieldClass);
467
+ rb_global_variable(&rbffi_StructLayoutPointerFieldClass);
468
+
458
469
  rbffi_StructLayoutFunctionFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Function", rbffi_StructLayoutFieldClass);
459
470
  rb_global_variable(&rbffi_StructLayoutFunctionFieldClass);
460
471
 
@@ -478,7 +489,7 @@ rbffi_StructLayout_Init(VALUE moduleFFI)
478
489
  rb_define_method(rbffi_StructLayoutArrayFieldClass, "put", array_field_put, 2);
479
490
 
480
491
  rb_define_alloc_func(rbffi_StructLayoutClass, struct_layout_allocate);
481
- rb_define_method(rbffi_StructLayoutClass, "initialize", struct_layout_initialize, 4);
492
+ rb_define_method(rbffi_StructLayoutClass, "initialize", struct_layout_initialize, 3);
482
493
  rb_define_method(rbffi_StructLayoutClass, "[]", struct_layout_aref, 1);
483
494
  rb_define_method(rbffi_StructLayoutClass, "fields", struct_layout_fields, 0);
484
495
  rb_define_method(rbffi_StructLayoutClass, "members", struct_layout_members, 0);
data/ext/ffi_c/Type.c CHANGED
@@ -1,28 +1,19 @@
1
1
  /*
2
2
  * Copyright (c) 2009, Wayne Meissner
3
- * All rights reserved.
4
3
  *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
4
+ * This file is part of ruby-ffi.
7
5
  *
8
- * * Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above copyright notice
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- * * The name of the author or authors may not be used to endorse or promote
14
- * products derived from this software without specific prior written permission.
6
+ * This code is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Lesser General Public License version 3 only, as
8
+ * published by the Free Software Foundation.
15
9
  *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10
+ * This code is distributed in the hope that it will be useful, but WITHOUT
11
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ * version 3 for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
26
17
  */
27
18
 
28
19
  #include <sys/param.h>
@@ -42,7 +33,7 @@ typedef struct BuiltinType_ {
42
33
 
43
34
  static void builtin_type_free(BuiltinType *);
44
35
 
45
- VALUE rbffi_TypeClass = Qnil, rbffi_EnumTypeClass = Qnil;
36
+ VALUE rbffi_TypeClass = Qnil;
46
37
 
47
38
  static VALUE classBuiltinType = Qnil;
48
39
  static VALUE typeMap = Qnil, sizeMap = Qnil;
@@ -104,41 +95,12 @@ type_alignment(VALUE self)
104
95
  static VALUE
105
96
  type_inspect(VALUE self)
106
97
  {
107
- char buf[256];
108
98
  Type *type;
109
99
 
110
100
  Data_Get_Struct(self, Type, type);
111
- snprintf(buf, sizeof(buf), "#<FFI::Type:%p size=%d alignment=%d>",
112
- type, (int) type->ffiType->size, (int) type->ffiType->alignment);
113
-
114
- return rb_str_new2(buf);
115
- }
116
-
117
- static VALUE
118
- enum_allocate(VALUE klass)
119
- {
120
- Type* type;
121
- VALUE obj;
122
-
123
- obj = Data_Make_Struct(klass, Type, NULL, -1, type);
124
- type->nativeType = NATIVE_ENUM;
125
- type->ffiType = &ffi_type_sint;
126
-
127
- return obj;
128
- }
129
-
130
- int
131
- rbffi_Type_GetIntValue(VALUE type)
132
- {
133
- Type* t;
134
-
135
- if (!rb_obj_is_kind_of(type, rbffi_TypeClass)) {
136
- rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
137
- }
138
-
139
- Data_Get_Struct(type, Type, t);
140
101
 
141
- return t->nativeType;
102
+ return rb_sprintf("#<%s:%p size=%d alignment=%d>",
103
+ rb_obj_classname(self), type, (int) type->ffiType->size, (int) type->ffiType->alignment);
142
104
  }
143
105
 
144
106
  static VALUE
@@ -166,14 +128,11 @@ builtin_type_free(BuiltinType *type)
166
128
  static VALUE
167
129
  builtin_type_inspect(VALUE self)
168
130
  {
169
- char buf[256];
170
131
  BuiltinType *type;
171
132
 
172
133
  Data_Get_Struct(self, BuiltinType, type);
173
- snprintf(buf, sizeof(buf), "#<FFI::Type::Builtin:%s size=%d alignment=%d>",
174
- type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
175
-
176
- return rb_str_new2(buf);
134
+ return rb_sprintf("#<%s:%s size=%d alignment=%d>",
135
+ rb_obj_classname(self), type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
177
136
  }
178
137
 
179
138
  int
@@ -231,8 +190,7 @@ rbffi_Type_Find(VALUE name)
231
190
  VALUE rbType = rbffi_Type_Lookup(name);
232
191
 
233
192
  if (!RTEST(rbType)) {
234
- VALUE typeName = rb_funcall2(name, rb_intern("inspect"), 0, NULL);
235
- rb_raise(rb_eTypeError, "Invalid type (%s)", RSTRING_PTR(typeName));
193
+ rb_raise(rb_eTypeError, "invalid type, %s", RSTRING_PTR(rb_inspect(name)));
236
194
  }
237
195
 
238
196
  return rbType;
@@ -243,7 +201,6 @@ rbffi_Type_Init(VALUE moduleFFI)
243
201
  {
244
202
  VALUE moduleNativeType;
245
203
  VALUE classType = rbffi_TypeClass = rb_define_class_under(moduleFFI, "Type", rb_cObject);
246
- VALUE classEnum = rbffi_EnumTypeClass = rb_define_class_under(moduleFFI, "Enum", classType);
247
204
 
248
205
  rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new());
249
206
  rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new());
@@ -270,9 +227,7 @@ rbffi_Type_Init(VALUE moduleFFI)
270
227
  // Make Type::Builtin non-allocatable
271
228
  rb_undef_method(CLASS_OF(classBuiltinType), "new");
272
229
  rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
273
-
274
- rb_define_alloc_func(classEnum, enum_allocate);
275
-
230
+
276
231
  rb_global_variable(&rbffi_TypeClass);
277
232
  rb_global_variable(&classBuiltinType);
278
233
 
@@ -284,29 +239,45 @@ rbffi_Type_Init(VALUE moduleFFI)
284
239
  rb_define_const(moduleFFI, "TYPE_" #x, t); \
285
240
  } while(0)
286
241
 
242
+ #define A(old_type, new_type) do { \
243
+ VALUE t = rb_const_get(classType, rb_intern(#old_type)); \
244
+ rb_const_set(classType, rb_intern(#new_type), t); \
245
+ } while(0)
246
+
287
247
  T(VOID, &ffi_type_void);
288
248
  T(INT8, &ffi_type_sint8);
249
+ A(INT8, SCHAR);
250
+ A(INT8, CHAR);
289
251
  T(UINT8, &ffi_type_uint8);
252
+ A(UINT8, UCHAR);
253
+
290
254
  T(INT16, &ffi_type_sint16);
255
+ A(INT16, SHORT);
256
+ A(INT16, SSHORT);
291
257
  T(UINT16, &ffi_type_uint16);
258
+ A(UINT16, USHORT);
292
259
  T(INT32, &ffi_type_sint32);
260
+ A(INT32, INT);
261
+ A(INT32, SINT);
293
262
  T(UINT32, &ffi_type_uint32);
263
+ A(UINT32, UINT);
294
264
  T(INT64, &ffi_type_sint64);
265
+ A(INT64, LONG_LONG);
266
+ A(INT64, SLONG_LONG);
295
267
  T(UINT64, &ffi_type_uint64);
268
+ A(UINT64, ULONG_LONG);
296
269
  T(LONG, &ffi_type_slong);
270
+ A(LONG, SLONG);
297
271
  T(ULONG, &ffi_type_ulong);
298
272
  T(FLOAT32, &ffi_type_float);
273
+ A(FLOAT32, FLOAT);
299
274
  T(FLOAT64, &ffi_type_double);
275
+ A(FLOAT64, DOUBLE);
300
276
  T(POINTER, &ffi_type_pointer);
301
277
  T(STRING, &ffi_type_pointer);
302
- T(RBXSTRING, &ffi_type_pointer);
303
278
  T(BUFFER_IN, &ffi_type_pointer);
304
279
  T(BUFFER_OUT, &ffi_type_pointer);
305
280
  T(BUFFER_INOUT, &ffi_type_pointer);
306
- T(ENUM, &ffi_type_sint);
307
281
  T(BOOL, &ffi_type_uchar);
308
-
309
-
310
- T(CHAR_ARRAY, &ffi_type_void);
311
282
  T(VARARGS, &ffi_type_void);
312
283
  }
data/ext/ffi_c/Type.h CHANGED
@@ -1,28 +1,19 @@
1
1
  /*
2
2
  * Copyright (c) 2009, Wayne Meissner
3
- * All rights reserved.
4
3
  *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
4
+ * This file is part of ruby-ffi.
7
5
  *
8
- * * Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above copyright notice
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- * * The name of the author or authors may not be used to endorse or promote
14
- * products derived from this software without specific prior written permission.
6
+ * This code is free software: you can redistribute it and/or modify it under
7
+ * the terms of the GNU Lesser General Public License version 3 only, as
8
+ * published by the Free Software Foundation.
15
9
  *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
10
+ * This code is distributed in the hope that it will be useful, but WITHOUT
11
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ * version 3 for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
26
17
  */
27
18
 
28
19
  #ifndef RBFFI_TYPE_H
@@ -44,8 +35,7 @@ struct Type_ {
44
35
  ffi_type* ffiType;
45
36
  };
46
37
 
47
- extern VALUE rbffi_TypeClass, rbffi_EnumTypeClass;
48
- extern int rbffi_Type_GetIntValue(VALUE type);
38
+ extern VALUE rbffi_TypeClass;
49
39
  extern VALUE rbffi_Type_Lookup(VALUE type);
50
40
  extern VALUE rbffi_Type_Find(VALUE type);
51
41
 
data/ext/ffi_c/Types.c CHANGED
@@ -34,9 +34,10 @@
34
34
  #include "StructByValue.h"
35
35
  #include "Types.h"
36
36
  #include "Struct.h"
37
+ #include "MappedType.h"
37
38
  #include "MemoryPointer.h"
38
39
 
39
- static ID id_find = 0;
40
+ static ID id_from_native = 0;
40
41
 
41
42
 
42
43
  VALUE
@@ -76,14 +77,15 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
76
77
  case NATIVE_POINTER:
77
78
  return rbffi_Pointer_NewInstance(*(void **) ptr);
78
79
  case NATIVE_BOOL:
79
- return ((int) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
80
- case NATIVE_ENUM:
81
- return rb_funcall(rbType, id_find, 1, INT2NUM((unsigned int) *(ffi_arg *) ptr));
80
+ return ((unsigned char) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
82
81
 
83
82
  case NATIVE_FUNCTION:
84
83
  case NATIVE_CALLBACK: {
85
- return rbffi_Function_NewInstance(rbType, rbffi_Pointer_NewInstance(*(void **) ptr));
84
+ return *(void **) ptr != NULL
85
+ ? rbffi_Function_NewInstance(rbType, rbffi_Pointer_NewInstance(*(void **) ptr))
86
+ : Qnil;
86
87
  }
88
+
87
89
  case NATIVE_STRUCT: {
88
90
  StructByValue* sbv = (StructByValue *)type;
89
91
  AbstractMemory* mem;
@@ -95,6 +97,19 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
95
97
  return rb_class_new_instance(1, &rbMemory, sbv->rbStructClass);
96
98
  }
97
99
 
100
+ case NATIVE_MAPPED: {
101
+ // For mapped types, first convert to the real native type, then upcall to
102
+ // ruby to convert to the expected return type
103
+ MappedType* m;
104
+ VALUE values[2];
105
+
106
+ Data_Get_Struct(rbType, MappedType, m);
107
+ values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr, enums);
108
+ values[1] = Qnil;
109
+
110
+ return rb_funcall2(m->rbConverter, id_from_native, 2, values);
111
+ }
112
+
98
113
  default:
99
114
  rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
100
115
  return Qnil;
@@ -104,6 +119,6 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
104
119
  void
105
120
  rbffi_Types_Init(VALUE moduleFFI)
106
121
  {
107
- id_find = rb_intern("find");
122
+ id_from_native = rb_intern("from_native");
108
123
  }
109
124
 
data/ext/ffi_c/Types.h CHANGED
@@ -57,20 +57,20 @@ typedef enum {
57
57
  NATIVE_CHAR_ARRAY,
58
58
  NATIVE_BOOL,
59
59
 
60
- /**
61
- * An immutable string. Nul terminated, but only copies in to the native function
62
- */
60
+ /** An immutable string. Nul terminated, but only copies in to the native function */
63
61
  NATIVE_STRING,
64
- /** A Rubinus :string arg - copies data both ways, and nul terminates */
65
- NATIVE_RBXSTRING,
62
+
66
63
  /** The function takes a variable number of arguments */
67
64
  NATIVE_VARARGS,
68
- /** A typedef-ed enum */
69
- NATIVE_ENUM,
65
+
70
66
  /** Struct-by-value param or result */
71
67
  NATIVE_STRUCT,
68
+
72
69
  /** An array type definition */
73
70
  NATIVE_ARRAY,
71
+
72
+ /** Custom native type */
73
+ NATIVE_MAPPED,
74
74
  } NativeType;
75
75
 
76
76
  #include <ffi.h>
data/ext/ffi_c/Variadic.c CHANGED
@@ -155,7 +155,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
155
155
  void** ffiValues;
156
156
  ffi_type** ffiParamTypes;
157
157
  ffi_type* ffiReturnType;
158
- NativeType* paramTypes;
158
+ Type** paramTypes;
159
159
  VALUE* argv;
160
160
  int paramCount = 0, i;
161
161
  ffi_status ffiStatus;
@@ -165,7 +165,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
165
165
 
166
166
  Data_Get_Struct(self, VariadicInvoker, invoker);
167
167
  paramCount = RARRAY_LEN(parameterTypes);
168
- paramTypes = ALLOCA_N(NativeType, paramCount);
168
+ paramTypes = ALLOCA_N(Type *, paramCount);
169
169
  ffiParamTypes = ALLOCA_N(ffi_type *, paramCount);
170
170
  params = ALLOCA_N(FFIStorage, paramCount);
171
171
  ffiValues = ALLOCA_N(void*, paramCount);
@@ -173,36 +173,40 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
173
173
  retval = alloca(MAX(invoker->returnType->ffiType->size, FFI_SIZEOF_ARG));
174
174
 
175
175
  for (i = 0; i < paramCount; ++i) {
176
- VALUE entry = rb_ary_entry(parameterTypes, i);
177
- int paramType = rbffi_Type_GetIntValue(entry);
178
- Type* type;
179
- Data_Get_Struct(entry, Type, type);
176
+ VALUE rbType = rb_ary_entry(parameterTypes, i);
177
+
178
+ if (!rb_obj_is_kind_of(rbType, rbffi_TypeClass)) {
179
+ rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
180
+ }
181
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
180
182
 
181
- switch (paramType) {
183
+ switch (paramTypes[i]->nativeType) {
182
184
  case NATIVE_INT8:
183
185
  case NATIVE_INT16:
184
186
  case NATIVE_INT32:
185
- case NATIVE_ENUM:
186
- paramType = NATIVE_INT32;
187
- ffiParamTypes[i] = &ffi_type_sint;
187
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("INT32"));
188
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
188
189
  break;
189
190
  case NATIVE_UINT8:
190
191
  case NATIVE_UINT16:
191
192
  case NATIVE_UINT32:
192
- paramType = NATIVE_UINT32;
193
- ffiParamTypes[i] = &ffi_type_uint;
193
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("UINT32"));
194
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
194
195
  break;
196
+
195
197
  case NATIVE_FLOAT32:
196
- paramType = NATIVE_FLOAT64;
197
- ffiParamTypes[i] = &ffi_type_double;
198
+ rbType = rb_const_get(rbffi_TypeClass, rb_intern("DOUBLE"));
199
+ Data_Get_Struct(rbType, Type, paramTypes[i]);
198
200
  break;
201
+
199
202
  default:
200
- ffiParamTypes[i] = type->ffiType;
201
203
  break;
202
204
  }
203
- paramTypes[i] = paramType;
205
+
206
+
207
+ ffiParamTypes[i] = paramTypes[i]->ffiType;
204
208
  if (ffiParamTypes[i] == NULL) {
205
- rb_raise(rb_eArgError, "Invalid parameter type #%x", paramType);
209
+ rb_raise(rb_eArgError, "Invalid parameter type #%x", paramTypes[i]);
206
210
  }
207
211
  argv[i] = rb_ary_entry(parameterValues, i);
208
212
  }
data/ext/ffi_c/extconf.rb CHANGED
@@ -15,9 +15,13 @@ unless Config::CONFIG['host_os'] =~ /mswin32|mingw32/
15
15
  end
16
16
 
17
17
  have_func('rb_thread_blocking_region')
18
+ have_func('ruby_thread_has_gvl_p')
19
+ have_func('ruby_native_thread_p')
20
+ have_func('rb_thread_call_with_gvl')
18
21
 
19
22
  $defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works
20
23
  $defs << "-DUSE_INTERNAL_LIBFFI" unless libffi_ok
24
+ $defs << "-DRUBY_1_9" if RUBY_VERSION >= "1.9.0"
21
25
 
22
26
  create_header
23
27
 
data/ext/ffi_c/ffi.c CHANGED
@@ -35,9 +35,9 @@
35
35
  #include "AbstractMemory.h"
36
36
  #include "Pointer.h"
37
37
  #include "MemoryPointer.h"
38
- #include "AutoPointer.h"
39
38
  #include "Struct.h"
40
39
  #include "StructByValue.h"
40
+ #include "StructByReference.h"
41
41
  #include "DynamicLibrary.h"
42
42
  #include "Platform.h"
43
43
  #include "Types.h"
@@ -47,6 +47,7 @@
47
47
  #include "MethodHandle.h"
48
48
  #include "Call.h"
49
49
  #include "ArrayType.h"
50
+ #include "MappedType.h"
50
51
 
51
52
  void Init_ffi_c(void);
52
53
 
@@ -59,8 +60,12 @@ Init_ffi_c(void) {
59
60
  rbffi_FFIModule = moduleFFI = rb_define_module("FFI");
60
61
  rb_global_variable(&moduleFFI);
61
62
 
63
+
62
64
  // FFI::Type needs to be initialized before most other classes
63
65
  rbffi_Type_Init(moduleFFI);
66
+
67
+ rbffi_DataConverter_Init(moduleFFI);
68
+
64
69
  rbffi_ArrayType_Init(moduleFFI);
65
70
  rbffi_LastError_Init(moduleFFI);
66
71
  rbffi_Call_Init(moduleFFI);
@@ -69,14 +74,15 @@ Init_ffi_c(void) {
69
74
  rbffi_Platform_Init(moduleFFI);
70
75
  rbffi_AbstractMemory_Init(moduleFFI);
71
76
  rbffi_Pointer_Init(moduleFFI);
72
- rbffi_AutoPointer_Init(moduleFFI);
73
77
  rbffi_Function_Init(moduleFFI);
74
78
  rbffi_MemoryPointer_Init(moduleFFI);
75
79
  rbffi_Buffer_Init(moduleFFI);
76
80
  rbffi_StructByValue_Init(moduleFFI);
81
+ rbffi_StructByReference_Init(moduleFFI);
77
82
  rbffi_Struct_Init(moduleFFI);
78
83
  rbffi_DynamicLibrary_Init(moduleFFI);
79
84
  rbffi_Variadic_Init(moduleFFI);
80
85
  rbffi_Types_Init(moduleFFI);
86
+ rbffi_MappedType_Init(moduleFFI);
81
87
  }
82
88
 
@@ -9021,7 +9021,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
9021
9021
  old_archive_from_new_cmds='true'
9022
9022
  # FIXME: Should let the user specify the lib program.
9023
9023
  old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
9024
- fix_srcfile_path='`cygpath -w "$srcfile"`'
9024
+ # fix_srcfile_path='`cygpath -w "$srcfile"`'
9025
9025
  enable_shared_with_static_runtimes=yes
9026
9026
  ;;
9027
9027
 
@@ -14,7 +14,7 @@ LIBFFI_BUILD_DIR = $(BUILD_DIR)/libffi
14
14
  ifeq ($(srcdir),.)
15
15
  LIBFFI_SRC_DIR := $(shell pwd)/libffi
16
16
  else
17
- LIBFFI_SRC_DIR := $(srcdir)/libffi
17
+ LIBFFI_SRC_DIR := $(abspath $(srcdir)/libffi)
18
18
  endif
19
19
 
20
20
  LIBFFI = $(LIBFFI_BUILD_DIR)/.libs/libffi_convenience.a
data/ext/ffi_c/libffi.mk CHANGED
@@ -7,7 +7,7 @@ $(LIBFFI):
7
7
  @if [ ! -f $(LIBFFI_BUILD_DIR)/Makefile ]; then \
8
8
  echo "Configuring libffi"; \
9
9
  cd $(LIBFFI_BUILD_DIR) && \
10
- /usr/bin/env CC="$(CC)" LD="$(LD)" CFLAGS="$(LIBFFI_CFLAGS)" \
10
+ /usr/bin/env CFLAGS="$(LIBFFI_CFLAGS)" \
11
11
  /bin/sh $(LIBFFI_CONFIGURE) $(LIBFFI_HOST) > /dev/null; \
12
12
  fi
13
13
  cd $(LIBFFI_BUILD_DIR) && $(MAKE)