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
data/ext/ffi_c/Struct.c CHANGED
@@ -45,16 +45,6 @@
45
45
  #include "StructByValue.h"
46
46
  #include "ArrayType.h"
47
47
 
48
- #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
49
-
50
- typedef struct StructLayoutBuilder {
51
- VALUE rbFieldNames;
52
- VALUE rbFieldMap;
53
- unsigned int size;
54
- unsigned int alignment;
55
- bool isUnion;
56
- } StructLayoutBuilder;
57
-
58
48
  typedef struct InlineArray_ {
59
49
  VALUE rbMemory;
60
50
  VALUE rbField;
@@ -69,14 +59,11 @@ typedef struct InlineArray_ {
69
59
 
70
60
 
71
61
  static void struct_mark(Struct *);
72
- static void struct_layout_builder_mark(StructLayoutBuilder *);
73
- static void struct_layout_builder_free(StructLayoutBuilder *);
62
+ static VALUE struct_class_layout(VALUE klass);
63
+ static void struct_malloc(Struct* s);
74
64
  static void inline_array_mark(InlineArray *);
75
65
 
76
- static inline int align(int offset, int align);
77
-
78
66
  VALUE rbffi_StructClass = Qnil;
79
- static VALUE StructLayoutBuilderClass = Qnil;
80
67
 
81
68
  VALUE rbffi_StructInlineArrayClass = Qnil;
82
69
  VALUE rbffi_StructLayoutCharArrayClass = Qnil;
@@ -116,10 +103,8 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
116
103
  /* Call up into ruby code to adjust the layout */
117
104
  if (nargs > 1) {
118
105
  s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
119
- } else if (rb_cvar_defined(klass, id_layout_ivar)) {
120
- s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
121
106
  } else {
122
- rb_raise(rb_eRuntimeError, "No Struct layout configured");
107
+ s->rbLayout = struct_class_layout(klass);
123
108
  }
124
109
 
125
110
  if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
@@ -132,13 +117,74 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
132
117
  s->pointer = MEMORY(rbPointer);
133
118
  s->rbPointer = rbPointer;
134
119
  } else {
135
- s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
136
- s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
120
+ struct_malloc(s);
137
121
  }
138
122
 
139
123
  return self;
140
124
  }
141
125
 
126
+ static VALUE
127
+ struct_class_layout(VALUE klass)
128
+ {
129
+ VALUE layout;
130
+ if (!rb_cvar_defined(klass, id_layout_ivar)) {
131
+ rb_raise(rb_eRuntimeError, "no Struct layout configured for %s", rb_class2name(klass));
132
+ }
133
+
134
+ layout = rb_cvar_get(klass, id_layout_ivar);
135
+ if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
136
+ rb_raise(rb_eRuntimeError, "invalid Struct layout for %s", rb_class2name(klass));
137
+ }
138
+
139
+ return layout;
140
+ }
141
+
142
+ static StructLayout*
143
+ struct_layout(VALUE self)
144
+ {
145
+ Struct* s = (Struct *) DATA_PTR(self);
146
+ if (s->layout != NULL) {
147
+ return s->layout;
148
+ }
149
+
150
+ if (s->layout == NULL) {
151
+ s->rbLayout = struct_class_layout(CLASS_OF(self));
152
+ Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
153
+ }
154
+
155
+ return s->layout;
156
+ }
157
+
158
+ static Struct*
159
+ struct_validate(VALUE self)
160
+ {
161
+ Struct* s;
162
+ Data_Get_Struct(self, Struct, s);
163
+
164
+ if (struct_layout(self) == NULL) {
165
+ rb_raise(rb_eRuntimeError, "struct layout == null");
166
+ }
167
+
168
+ if (s->pointer == NULL) {
169
+ struct_malloc(s);
170
+ }
171
+
172
+ return s;
173
+ }
174
+
175
+ static void
176
+ struct_malloc(Struct* s)
177
+ {
178
+ if (s->rbPointer == Qnil) {
179
+ s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
180
+
181
+ } else if (!rb_obj_is_kind_of(s->rbPointer, rbffi_AbstractMemoryClass)) {
182
+ rb_raise(rb_eRuntimeError, "invalid pointer in struct");
183
+ }
184
+
185
+ s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
186
+ }
187
+
142
188
  static void
143
189
  struct_mark(Struct *s)
144
190
  {
@@ -151,8 +197,9 @@ struct_field(Struct* s, VALUE fieldName)
151
197
  {
152
198
  StructLayout* layout = s->layout;
153
199
  VALUE rbField;
154
- if (layout == NULL) {
155
- rb_raise(rb_eRuntimeError, "layout not set for Struct");
200
+
201
+ if (likely(SYMBOL_P(fieldName) && st_lookup(layout->fieldSymbolTable, fieldName, (st_data_t *) &rbField))) {
202
+ return rbField;
156
203
  }
157
204
 
158
205
  rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
@@ -170,8 +217,9 @@ struct_aref(VALUE self, VALUE fieldName)
170
217
  Struct* s;
171
218
  VALUE rbField;
172
219
  StructField* f;
173
-
174
- Data_Get_Struct(self, Struct, s);
220
+
221
+ s = struct_validate(self);
222
+
175
223
  rbField = struct_field(s, fieldName);
176
224
  f = (StructField *) DATA_PTR(rbField);
177
225
 
@@ -196,7 +244,8 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
196
244
  StructField* f;
197
245
 
198
246
 
199
- Data_Get_Struct(self, Struct, s);
247
+ s = struct_validate(self);
248
+
200
249
  rbField = struct_field(s, fieldName);
201
250
  f = (StructField *) DATA_PTR(rbField);
202
251
  if (f->put != NULL) {
@@ -221,12 +270,25 @@ static VALUE
221
270
  struct_set_pointer(VALUE self, VALUE pointer)
222
271
  {
223
272
  Struct* s;
273
+ StructLayout* layout;
274
+ AbstractMemory* memory;
224
275
 
225
276
  if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
226
- rb_raise(rb_eArgError, "Invalid pointer");
277
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Pointer or Buffer)",
278
+ rb_obj_classname(pointer));
279
+ return Qnil;
227
280
  }
228
281
 
282
+
229
283
  Data_Get_Struct(self, Struct, s);
284
+ Data_Get_Struct(pointer, AbstractMemory, memory);
285
+ layout = struct_layout(self);
286
+
287
+ if (layout->base.ffiType->size > memory->size) {
288
+ rb_raise(rb_eArgError, "memory of %d bytes too small for struct %s (expected at least %d)",
289
+ memory->size, rb_obj_classname(self), layout->base.ffiType->size);
290
+ }
291
+
230
292
  s->pointer = MEMORY(pointer);
231
293
  s->rbPointer = pointer;
232
294
  rb_ivar_set(self, id_pointer_ivar, pointer);
@@ -251,7 +313,9 @@ struct_set_layout(VALUE self, VALUE layout)
251
313
  Data_Get_Struct(self, Struct, s);
252
314
 
253
315
  if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
254
- rb_raise(rb_eArgError, "Invalid Struct layout");
316
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
317
+ rb_obj_classname(layout), rb_class2name(rbffi_StructLayoutClass));
318
+ return Qnil;
255
319
  }
256
320
 
257
321
  Data_Get_Struct(layout, StructLayout, s->layout);
@@ -270,293 +334,35 @@ struct_get_layout(VALUE self)
270
334
  return s->rbLayout;
271
335
  }
272
336
 
273
- static VALUE
274
- struct_layout_builder_allocate(VALUE klass)
275
- {
276
- StructLayoutBuilder* builder;
277
- VALUE obj;
278
-
279
- obj = Data_Make_Struct(klass, StructLayoutBuilder, struct_layout_builder_mark, struct_layout_builder_free, builder);
280
-
281
- builder->size = 0;
282
- builder->alignment = 1;
283
- builder->isUnion = false;
284
- builder->rbFieldNames = rb_ary_new();
285
- builder->rbFieldMap = rb_hash_new();
286
-
287
- return obj;
288
- }
289
-
290
- static void
291
- struct_layout_builder_mark(StructLayoutBuilder* builder)
292
- {
293
- rb_gc_mark(builder->rbFieldNames);
294
- rb_gc_mark(builder->rbFieldMap);
295
- }
296
-
297
- static void
298
- struct_layout_builder_free(StructLayoutBuilder* builder)
299
- {
300
- xfree(builder);
301
- }
302
-
303
- static VALUE
304
- struct_layout_builder_initialize(VALUE self)
305
- {
306
- StructLayoutBuilder* builder;
307
-
308
- Data_Get_Struct(self, StructLayoutBuilder, builder);
309
-
310
- return self;
311
- }
312
-
313
- static VALUE
314
- struct_layout_builder_get_size(VALUE self)
315
- {
316
- StructLayoutBuilder* builder;
317
-
318
- Data_Get_Struct(self, StructLayoutBuilder, builder);
319
-
320
- return UINT2NUM(builder->size);
321
- }
322
-
323
- static VALUE
324
- struct_layout_builder_set_size(VALUE self, VALUE rbSize)
325
- {
326
- StructLayoutBuilder* builder;
327
- unsigned int size = NUM2UINT(rbSize);
328
-
329
- Data_Get_Struct(self, StructLayoutBuilder, builder);
330
- builder->size = MAX(size, builder->size);
331
-
332
- return UINT2NUM(builder->size);
333
- }
334
-
335
- static VALUE
336
- struct_layout_builder_get_alignment(VALUE self)
337
- {
338
- StructLayoutBuilder* builder;
339
-
340
- Data_Get_Struct(self, StructLayoutBuilder, builder);
341
-
342
- return UINT2NUM(builder->alignment);
343
- }
344
337
 
345
338
  static VALUE
346
- struct_layout_builder_set_alignment(VALUE self, VALUE rbAlign)
339
+ struct_null_p(VALUE self)
347
340
  {
348
- StructLayoutBuilder* builder;
349
- unsigned int align = NUM2UINT(rbAlign);
350
-
351
- Data_Get_Struct(self, StructLayoutBuilder, builder);
352
- builder->size = MAX(align, builder->alignment);
353
-
354
- return UINT2NUM(builder->alignment);
355
- }
356
-
357
- static VALUE
358
- struct_layout_builder_set_union(VALUE self, VALUE rbUnion)
359
- {
360
- StructLayoutBuilder* builder;
361
-
341
+ Struct* s;
362
342
 
363
- Data_Get_Struct(self, StructLayoutBuilder, builder);
364
- builder->isUnion = RTEST(rbUnion);
343
+ Data_Get_Struct(self, Struct, s);
365
344
 
366
- return rbUnion;
345
+ return s->pointer->address == NULL ? Qtrue : Qfalse;
367
346
  }
368
347
 
369
348
  static VALUE
370
- struct_layout_builder_union_p(VALUE self)
371
- {
372
- StructLayoutBuilder* builder;
373
-
374
-
375
- Data_Get_Struct(self, StructLayoutBuilder, builder);
376
-
377
-
378
- return builder->isUnion ? Qtrue : Qfalse;
379
- }
380
-
381
- static void
382
- store_field(StructLayoutBuilder* builder, VALUE rbName, VALUE rbField,
383
- unsigned int offset, unsigned int size, unsigned int alignment)
349
+ struct_order(int argc, VALUE* argv, VALUE self)
384
350
  {
385
- rb_ary_push(builder->rbFieldNames, rbName);
386
- rb_hash_aset(builder->rbFieldMap, rbName, rbField);
387
-
388
- builder->alignment = MAX(builder->alignment, alignment);
351
+ Struct* s;
389
352
 
390
- if (builder->isUnion) {
391
- builder->size = MAX(builder->size, size);
392
- } else {
393
- builder->size = MAX(builder->size, offset + size);
394
- }
395
- }
353
+ Data_Get_Struct(self, Struct, s);
354
+ if (argc == 0) {
355
+ return rb_funcall(s->rbPointer, rb_intern("order"), 0);
396
356
 
397
- static int
398
- calculate_offset(StructLayoutBuilder* builder, int alignment, VALUE rbOffset)
399
- {
400
- if (rbOffset != Qnil) {
401
- return NUM2UINT(rbOffset);
402
357
  } else {
403
- return builder->isUnion ? 0 : align(builder->size, alignment);
404
- }
405
- }
406
-
407
- static VALUE
408
- struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
409
- {
410
- StructLayoutBuilder* builder;
411
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
412
- unsigned int size, alignment, offset;
413
- int nargs;
414
-
415
- nargs = rb_scan_args(argc, argv, "21", &rbName, &rbType, &rbOffset);
416
-
417
- Data_Get_Struct(self, StructLayoutBuilder, builder);
418
-
419
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
420
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
421
-
422
- offset = calculate_offset(builder, alignment, rbOffset);
423
-
424
- //
425
- // If a primitive type was passed in as the type arg, try and convert
426
- //
427
- if (!rb_obj_is_kind_of(rbType, rbffi_StructLayoutFieldClass)) {
428
- VALUE fargv[3], rbFieldClass;
429
- fargv[0] = rbName;
430
- fargv[1] = UINT2NUM(offset);
431
- fargv[2] = rbType;
358
+ VALUE retval = rb_obj_dup(self);
359
+ VALUE rbPointer = rb_funcall2(s->rbPointer, rb_intern("order"), argc, argv);
360
+ struct_set_pointer(retval, rbPointer);
432
361
 
433
- if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
434
-
435
- rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
436
-
437
- } else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
438
-
439
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
440
-
441
- } else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
442
-
443
- rbFieldClass = rbffi_StructLayoutArrayFieldClass;
444
-
445
- } else if (rb_obj_is_kind_of(rbType, rbffi_EnumTypeClass)) {
446
-
447
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("Enum"));
448
-
449
- } else {
450
- rbFieldClass = rbffi_StructLayoutFieldClass;
451
- }
452
-
453
- if (!RTEST(rbFieldClass)) {
454
- rb_raise(rb_eTypeError, "invalid struct field type (%s)", rb_obj_classname(rbType));
455
- return Qnil;
456
- }
457
-
458
- rbField = rb_class_new_instance(3, fargv, rbFieldClass);
459
- } else {
460
- rbField = rbType;
362
+ return retval;
461
363
  }
462
-
463
- store_field(builder, rbName, rbField, offset, size, alignment);
464
-
465
- return self;
466
364
  }
467
365
 
468
- static VALUE
469
- struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
470
- {
471
- StructLayoutBuilder* builder;
472
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
473
- VALUE rbFieldClass = Qnil, rbStructClass = Qnil;
474
- VALUE fargv[3];
475
- unsigned int size, alignment, offset;
476
- int nargs;
477
-
478
- nargs = rb_scan_args(argc, argv, "21", &rbName, &rbStructClass, &rbOffset);
479
-
480
- if (!rb_obj_is_instance_of(rbStructClass, rb_cClass) || !rb_class_inherited(rbStructClass, rbffi_StructClass)) {
481
- rb_raise(rb_eTypeError, "wrong argument type. Expected subclass of FFI::Struct");
482
- }
483
-
484
- rbType = rb_class_new_instance(1, &rbStructClass, rbffi_StructByValueClass);
485
-
486
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
487
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
488
-
489
- Data_Get_Struct(self, StructLayoutBuilder, builder);
490
-
491
- offset = calculate_offset(builder, alignment, rbOffset);
492
-
493
- fargv[0] = rbName;
494
- fargv[1] = UINT2NUM(offset);
495
- fargv[2] = rbType;
496
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
497
- if (!RTEST(rbFieldClass)) {
498
- rb_raise(rb_eRuntimeError, "could not locate StructLayout::InlineStruct");
499
- return Qnil;
500
- }
501
-
502
- rbField = rb_class_new_instance(3, fargv, rbFieldClass);
503
-
504
- store_field(builder, rbName, rbField, offset, size, alignment);
505
-
506
- return self;
507
- }
508
-
509
- static VALUE
510
- struct_layout_builder_add_array(int argc, VALUE* argv, VALUE self)
511
- {
512
- StructLayoutBuilder* builder;
513
- VALUE rbName = Qnil, rbType = Qnil, rbLength = Qnil, rbOffset = Qnil, rbField;
514
- VALUE fargv[3], aargv[2];
515
- unsigned int size, alignment, offset;
516
- int nargs;
517
-
518
- nargs = rb_scan_args(argc, argv, "31", &rbName, &rbType, &rbLength, &rbOffset);
519
-
520
- Data_Get_Struct(self, StructLayoutBuilder, builder);
521
-
522
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
523
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL)) * NUM2UINT(rbLength);
524
-
525
- offset = calculate_offset(builder, alignment, rbOffset);
526
-
527
- aargv[0] = rbType;
528
- aargv[1] = rbLength;
529
- fargv[0] = rbName;
530
- fargv[1] = UINT2NUM(offset);
531
- fargv[2] = rb_class_new_instance(2, aargv, rbffi_ArrayTypeClass);
532
- rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutArrayFieldClass);
533
-
534
- store_field(builder, rbName, rbField, offset, size, alignment);
535
-
536
- return self;
537
- }
538
-
539
- static inline int
540
- align(int offset, int align)
541
- {
542
- return align + ((offset - 1) & ~(align - 1));
543
- }
544
-
545
- static VALUE
546
- struct_layout_builder_build(VALUE self)
547
- {
548
- StructLayoutBuilder* builder;
549
- VALUE argv[4];
550
-
551
- Data_Get_Struct(self, StructLayoutBuilder, builder);
552
-
553
- argv[0] = builder->rbFieldNames;
554
- argv[1] = builder->rbFieldMap;
555
- argv[2] = UINT2NUM(align(builder->size, builder->alignment)); // tail padding
556
- argv[3] = UINT2NUM(builder->alignment);
557
-
558
- return rb_class_new_instance(4, argv, rbffi_StructLayoutClass);
559
- }
560
366
 
561
367
  static VALUE
562
368
  inline_array_allocate(VALUE klass)
@@ -773,10 +579,6 @@ rbffi_Struct_Init(VALUE moduleFFI)
773
579
  rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
774
580
  rb_global_variable(&rbffi_StructClass);
775
581
 
776
-
777
- StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
778
- rb_global_variable(&StructLayoutBuilderClass);
779
-
780
582
  rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
781
583
  rb_global_variable(&rbffi_StructInlineArrayClass);
782
584
 
@@ -787,6 +589,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
787
589
 
788
590
  rb_define_alloc_func(StructClass, struct_allocate);
789
591
  rb_define_method(StructClass, "initialize", struct_initialize, -1);
592
+ rb_define_method(StructClass, "order", struct_order, -1);
790
593
 
791
594
  rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
792
595
  rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
@@ -803,22 +606,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
803
606
 
804
607
  rb_define_method(StructClass, "[]", struct_aref, 1);
805
608
  rb_define_method(StructClass, "[]=", struct_aset, 2);
806
-
807
-
808
-
809
- rb_define_alloc_func(StructLayoutBuilderClass, struct_layout_builder_allocate);
810
- rb_define_method(StructLayoutBuilderClass, "initialize", struct_layout_builder_initialize, 0);
811
- rb_define_method(StructLayoutBuilderClass, "build", struct_layout_builder_build, 0);
812
-
813
- rb_define_method(StructLayoutBuilderClass, "alignment", struct_layout_builder_get_alignment, 0);
814
- rb_define_method(StructLayoutBuilderClass, "alignment=", struct_layout_builder_set_alignment, 1);
815
- rb_define_method(StructLayoutBuilderClass, "size", struct_layout_builder_get_size, 0);
816
- rb_define_method(StructLayoutBuilderClass, "size=", struct_layout_builder_set_size, 1);
817
- rb_define_method(StructLayoutBuilderClass, "union=", struct_layout_builder_set_union, 1);
818
- rb_define_method(StructLayoutBuilderClass, "union?", struct_layout_builder_union_p, 0);
819
- rb_define_method(StructLayoutBuilderClass, "add_field", struct_layout_builder_add_field, -1);
820
- rb_define_method(StructLayoutBuilderClass, "add_array", struct_layout_builder_add_array, -1);
821
- rb_define_method(StructLayoutBuilderClass, "add_struct", struct_layout_builder_add_struct, -1);
609
+ rb_define_method(StructClass, "null?", struct_null_p, 0);
822
610
 
823
611
  rb_include_module(rbffi_StructInlineArrayClass, rb_mEnumerable);
824
612
  rb_define_alloc_func(rbffi_StructInlineArrayClass, inline_array_allocate);
data/ext/ffi_c/Struct.h CHANGED
@@ -32,6 +32,11 @@
32
32
 
33
33
  #include "AbstractMemory.h"
34
34
  #include "Type.h"
35
+ #ifdef RUBY_1_9
36
+ #include <ruby/st.h>
37
+ #else
38
+ #include <st.h>
39
+ #endif
35
40
 
36
41
  #ifdef __cplusplus
37
42
  extern "C" {
@@ -63,6 +68,7 @@ extern "C" {
63
68
  int size;
64
69
  int align;
65
70
  ffi_type** ffiTypes;
71
+ struct st_table* fieldSymbolTable;
66
72
  VALUE rbFieldNames;
67
73
  VALUE rbFieldMap;
68
74
  VALUE rbFields;
@@ -0,0 +1,150 @@
1
+ /*
2
+ * Copyright (c) 2010, 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
+ #include <sys/param.h>
29
+ #include <sys/types.h>
30
+ #include <stdio.h>
31
+ #include <stdint.h>
32
+ #include <stdbool.h>
33
+ #include <errno.h>
34
+ #include <ruby.h>
35
+
36
+ #include <ffi.h>
37
+ #include "rbffi.h"
38
+ #include "compat.h"
39
+
40
+ #include "Pointer.h"
41
+ #include "Struct.h"
42
+ #include "StructByReference.h"
43
+
44
+
45
+ #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
46
+
47
+ static VALUE sbr_allocate(VALUE);
48
+ static VALUE sbr_initialize(VALUE, VALUE);
49
+ static void sbr_mark(StructByReference *);
50
+
51
+ VALUE rbffi_StructByReferenceClass = Qnil;
52
+
53
+ static VALUE
54
+ sbr_allocate(VALUE klass)
55
+ {
56
+ StructByReference* sbr;
57
+
58
+ VALUE obj = Data_Make_Struct(klass, StructByReference, sbr_mark, -1, sbr);
59
+
60
+ sbr->rbStructClass = Qnil;
61
+
62
+ return obj;
63
+ }
64
+
65
+ static VALUE
66
+ sbr_initialize(VALUE self, VALUE rbStructClass)
67
+ {
68
+ StructByReference* sbr = NULL;
69
+
70
+ if (!rb_class_inherited_p(rbStructClass, rbffi_StructClass)) {
71
+ rb_raise(rb_eTypeError, "wrong type (expected subclass of FFI::Struct)");
72
+ }
73
+
74
+ Data_Get_Struct(self, StructByReference, sbr);
75
+ sbr->rbStructClass = rbStructClass;
76
+
77
+ return self;
78
+ }
79
+
80
+ static void
81
+ sbr_mark(StructByReference *sbr)
82
+ {
83
+ rb_gc_mark(sbr->rbStructClass);
84
+ }
85
+
86
+
87
+ static VALUE
88
+ sbr_struct_class(VALUE self)
89
+ {
90
+ StructByReference* sbr;
91
+
92
+ Data_Get_Struct(self, StructByReference, sbr);
93
+
94
+ return sbr->rbStructClass;
95
+ }
96
+
97
+ static VALUE
98
+ sbr_native_type(VALUE self)
99
+ {
100
+ return rb_const_get(rbffi_TypeClass, rb_intern("POINTER"));
101
+ }
102
+
103
+ static VALUE
104
+ sbr_to_native(VALUE self, VALUE value, VALUE ctx)
105
+ {
106
+ StructByReference* sbr;
107
+ Struct* s;
108
+
109
+ if (unlikely(value == Qnil)) {
110
+ return rbffi_NullPointerSingleton;
111
+ }
112
+
113
+ Data_Get_Struct(self, StructByReference, sbr);
114
+ if (!rb_obj_is_kind_of(value, sbr->rbStructClass)) {
115
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
116
+ rb_obj_classname(value),
117
+ RSTRING_PTR(rb_class_name(sbr->rbStructClass)));
118
+ }
119
+
120
+ Data_Get_Struct(value, Struct, s);
121
+
122
+ return s->rbPointer;
123
+ }
124
+
125
+ static VALUE
126
+ sbr_from_native(VALUE self, VALUE value, VALUE ctx)
127
+ {
128
+ StructByReference* sbr;
129
+
130
+ Data_Get_Struct(self, StructByReference, sbr);
131
+
132
+ return rb_class_new_instance(1, &value, sbr->rbStructClass);
133
+ }
134
+
135
+
136
+ void
137
+ rbffi_StructByReference_Init(VALUE moduleFFI)
138
+ {
139
+ rbffi_StructByReferenceClass = rb_define_class_under(moduleFFI, "StructByReference", rb_cObject);
140
+ rb_global_variable(&rbffi_StructByReferenceClass);
141
+ rb_include_module(rbffi_StructByReferenceClass, rb_const_get(moduleFFI, rb_intern("DataConverter")));
142
+
143
+ rb_define_alloc_func(rbffi_StructByReferenceClass, sbr_allocate);
144
+ rb_define_method(rbffi_StructByReferenceClass, "initialize", sbr_initialize, 1);
145
+ rb_define_method(rbffi_StructByReferenceClass, "struct_class", sbr_struct_class, 0);
146
+ rb_define_method(rbffi_StructByReferenceClass, "native_type", sbr_native_type, 0);
147
+ rb_define_method(rbffi_StructByReferenceClass, "to_native", sbr_to_native, 2);
148
+ rb_define_method(rbffi_StructByReferenceClass, "from_native", sbr_from_native, 2);
149
+ }
150
+