ffi 0.6.4 → 1.0.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 (92) hide show
  1. data/History.txt +7 -0
  2. data/LICENSE +10 -21
  3. data/README.rdoc +70 -0
  4. data/Rakefile +56 -84
  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 +52 -540
  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 +252 -30
  13. data/ext/ffi_c/MappedType.c +146 -0
  14. data/{libtest/FunctionTest.c → ext/ffi_c/MappedType.h} +32 -25
  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 +19 -306
  19. data/ext/ffi_c/Struct.h +6 -0
  20. data/ext/ffi_c/StructByReference.c +150 -0
  21. data/{libtest/LastErrorTest.c → ext/ffi_c/StructByReference.h} +30 -21
  22. data/ext/ffi_c/StructLayout.c +26 -16
  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 +20 -5
  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/rbffi.h +1 -0
  31. data/lib/ffi/autopointer.rb +23 -22
  32. data/lib/ffi/enum.rb +36 -21
  33. data/lib/ffi/errno.rb +20 -0
  34. data/lib/ffi/ffi.rb +13 -80
  35. data/lib/ffi/io.rb +12 -20
  36. data/lib/ffi/library.rb +109 -92
  37. data/lib/ffi/managedstruct.rb +1 -1
  38. data/lib/ffi/memorypointer.rb +15 -21
  39. data/lib/ffi/platform.rb +27 -33
  40. data/lib/ffi/pointer.rb +14 -21
  41. data/lib/ffi/struct.rb +98 -49
  42. data/lib/ffi/struct_layout_builder.rb +158 -0
  43. data/lib/ffi/types.rb +99 -128
  44. data/lib/ffi/union.rb +20 -0
  45. data/lib/ffi/variadic.rb +33 -22
  46. data/spec/ffi/async_callback_spec.rb +23 -0
  47. data/spec/ffi/callback_spec.rb +62 -0
  48. data/spec/ffi/custom_param_type.rb +31 -0
  49. data/spec/ffi/custom_type_spec.rb +73 -0
  50. data/spec/ffi/enum_spec.rb +19 -0
  51. data/spec/ffi/ffi_spec.rb +24 -0
  52. data/spec/ffi/pointer_spec.rb +15 -0
  53. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
  54. data/spec/ffi/strptr_spec.rb +36 -0
  55. data/spec/ffi/struct_packed_spec.rb +46 -0
  56. data/spec/ffi/struct_spec.rb +19 -5
  57. data/spec/ffi/typedef_spec.rb +14 -0
  58. data/tasks/ann.rake +80 -0
  59. data/tasks/extension.rake +25 -0
  60. data/tasks/gem.rake +200 -0
  61. data/tasks/git.rake +41 -0
  62. data/tasks/notes.rake +27 -0
  63. data/tasks/post_load.rake +34 -0
  64. data/tasks/rdoc.rake +50 -0
  65. data/tasks/rubyforge.rake +55 -0
  66. data/tasks/setup.rb +301 -0
  67. data/tasks/spec.rake +54 -0
  68. data/tasks/svn.rake +47 -0
  69. data/tasks/test.rake +40 -0
  70. metadata +139 -131
  71. data/README.md +0 -109
  72. data/ext/ffi_c/AutoPointer.c +0 -60
  73. data/ext/ffi_c/AutoPointer.h +0 -18
  74. data/ext/ffi_c/Ffi_c.iml +0 -12
  75. data/ffi.gemspec +0 -18
  76. data/gen/log +0 -1
  77. data/lib/Lib.iml +0 -21
  78. data/libtest/Benchmark.c +0 -73
  79. data/libtest/BoolTest.c +0 -52
  80. data/libtest/BufferTest.c +0 -52
  81. data/libtest/ClosureTest.c +0 -173
  82. data/libtest/EnumTest.c +0 -55
  83. data/libtest/GNUmakefile +0 -141
  84. data/libtest/GlobalVariable.c +0 -56
  85. data/libtest/NumberTest.c +0 -145
  86. data/libtest/PointerTest.c +0 -84
  87. data/libtest/ReferenceTest.c +0 -44
  88. data/libtest/StringTest.c +0 -55
  89. data/libtest/StructTest.c +0 -247
  90. data/libtest/UnionTest.c +0 -64
  91. data/libtest/VariadicTest.c +0 -57
  92. data/spec/ffi/Ffi.iml +0 -12
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,16 +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 *);
74
62
  static VALUE struct_class_layout(VALUE klass);
75
63
  static void struct_malloc(Struct* s);
76
64
  static void inline_array_mark(InlineArray *);
77
65
 
78
- static inline int align(int offset, int align);
79
-
80
66
  VALUE rbffi_StructClass = Qnil;
81
- static VALUE StructLayoutBuilderClass = Qnil;
82
67
 
83
68
  VALUE rbffi_StructInlineArrayClass = Qnil;
84
69
  VALUE rbffi_StructLayoutCharArrayClass = Qnil;
@@ -213,6 +198,10 @@ struct_field(Struct* s, VALUE fieldName)
213
198
  StructLayout* layout = s->layout;
214
199
  VALUE rbField;
215
200
 
201
+ if (likely(SYMBOL_P(fieldName) && st_lookup(layout->fieldSymbolTable, fieldName, (st_data_t *) &rbField))) {
202
+ return rbField;
203
+ }
204
+
216
205
  rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
217
206
  if (rbField == Qnil) {
218
207
  VALUE str = rb_funcall2(fieldName, id_to_s, 0, NULL);
@@ -345,293 +334,35 @@ struct_get_layout(VALUE self)
345
334
  return s->rbLayout;
346
335
  }
347
336
 
348
- static VALUE
349
- struct_layout_builder_allocate(VALUE klass)
350
- {
351
- StructLayoutBuilder* builder;
352
- VALUE obj;
353
-
354
- obj = Data_Make_Struct(klass, StructLayoutBuilder, struct_layout_builder_mark, struct_layout_builder_free, builder);
355
-
356
- builder->size = 0;
357
- builder->alignment = 1;
358
- builder->isUnion = false;
359
- builder->rbFieldNames = rb_ary_new();
360
- builder->rbFieldMap = rb_hash_new();
361
-
362
- return obj;
363
- }
364
-
365
- static void
366
- struct_layout_builder_mark(StructLayoutBuilder* builder)
367
- {
368
- rb_gc_mark(builder->rbFieldNames);
369
- rb_gc_mark(builder->rbFieldMap);
370
- }
371
-
372
- static void
373
- struct_layout_builder_free(StructLayoutBuilder* builder)
374
- {
375
- xfree(builder);
376
- }
377
-
378
- static VALUE
379
- struct_layout_builder_initialize(VALUE self)
380
- {
381
- StructLayoutBuilder* builder;
382
-
383
- Data_Get_Struct(self, StructLayoutBuilder, builder);
384
-
385
- return self;
386
- }
387
-
388
- static VALUE
389
- struct_layout_builder_get_size(VALUE self)
390
- {
391
- StructLayoutBuilder* builder;
392
-
393
- Data_Get_Struct(self, StructLayoutBuilder, builder);
394
-
395
- return UINT2NUM(builder->size);
396
- }
397
-
398
- static VALUE
399
- struct_layout_builder_set_size(VALUE self, VALUE rbSize)
400
- {
401
- StructLayoutBuilder* builder;
402
- unsigned int size = NUM2UINT(rbSize);
403
-
404
- Data_Get_Struct(self, StructLayoutBuilder, builder);
405
- builder->size = MAX(size, builder->size);
406
-
407
- return UINT2NUM(builder->size);
408
- }
409
-
410
- static VALUE
411
- struct_layout_builder_get_alignment(VALUE self)
412
- {
413
- StructLayoutBuilder* builder;
414
-
415
- Data_Get_Struct(self, StructLayoutBuilder, builder);
416
-
417
- return UINT2NUM(builder->alignment);
418
- }
419
-
420
- static VALUE
421
- struct_layout_builder_set_alignment(VALUE self, VALUE rbAlign)
422
- {
423
- StructLayoutBuilder* builder;
424
- unsigned int align = NUM2UINT(rbAlign);
425
-
426
- Data_Get_Struct(self, StructLayoutBuilder, builder);
427
- builder->size = MAX(align, builder->alignment);
428
-
429
- return UINT2NUM(builder->alignment);
430
- }
431
337
 
432
338
  static VALUE
433
- struct_layout_builder_set_union(VALUE self, VALUE rbUnion)
339
+ struct_null_p(VALUE self)
434
340
  {
435
- StructLayoutBuilder* builder;
436
-
341
+ Struct* s;
437
342
 
438
- Data_Get_Struct(self, StructLayoutBuilder, builder);
439
- builder->isUnion = RTEST(rbUnion);
343
+ Data_Get_Struct(self, Struct, s);
440
344
 
441
- return rbUnion;
345
+ return s->pointer->address == NULL ? Qtrue : Qfalse;
442
346
  }
443
347
 
444
348
  static VALUE
445
- struct_layout_builder_union_p(VALUE self)
446
- {
447
- StructLayoutBuilder* builder;
448
-
449
-
450
- Data_Get_Struct(self, StructLayoutBuilder, builder);
451
-
452
-
453
- return builder->isUnion ? Qtrue : Qfalse;
454
- }
455
-
456
- static void
457
- store_field(StructLayoutBuilder* builder, VALUE rbName, VALUE rbField,
458
- unsigned int offset, unsigned int size, unsigned int alignment)
349
+ struct_order(int argc, VALUE* argv, VALUE self)
459
350
  {
460
- rb_ary_push(builder->rbFieldNames, rbName);
461
- rb_hash_aset(builder->rbFieldMap, rbName, rbField);
462
-
463
- builder->alignment = MAX(builder->alignment, alignment);
351
+ Struct* s;
464
352
 
465
- if (builder->isUnion) {
466
- builder->size = MAX(builder->size, size);
467
- } else {
468
- builder->size = MAX(builder->size, offset + size);
469
- }
470
- }
353
+ Data_Get_Struct(self, Struct, s);
354
+ if (argc == 0) {
355
+ return rb_funcall(s->rbPointer, rb_intern("order"), 0);
471
356
 
472
- static int
473
- calculate_offset(StructLayoutBuilder* builder, int alignment, VALUE rbOffset)
474
- {
475
- if (rbOffset != Qnil) {
476
- return NUM2UINT(rbOffset);
477
357
  } else {
478
- return builder->isUnion ? 0 : align(builder->size, alignment);
479
- }
480
- }
481
-
482
- static VALUE
483
- struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
484
- {
485
- StructLayoutBuilder* builder;
486
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
487
- unsigned int size, alignment, offset;
488
- int nargs;
489
-
490
- nargs = rb_scan_args(argc, argv, "21", &rbName, &rbType, &rbOffset);
491
-
492
- Data_Get_Struct(self, StructLayoutBuilder, builder);
493
-
494
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
495
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
496
-
497
- offset = calculate_offset(builder, alignment, rbOffset);
498
-
499
- //
500
- // If a primitive type was passed in as the type arg, try and convert
501
- //
502
- if (!rb_obj_is_kind_of(rbType, rbffi_StructLayoutFieldClass)) {
503
- VALUE fargv[3], rbFieldClass;
504
- fargv[0] = rbName;
505
- fargv[1] = UINT2NUM(offset);
506
- 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);
507
361
 
508
- if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
509
-
510
- rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
511
-
512
- } else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
513
-
514
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
515
-
516
- } else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
517
-
518
- rbFieldClass = rbffi_StructLayoutArrayFieldClass;
519
-
520
- } else if (rb_obj_is_kind_of(rbType, rbffi_EnumTypeClass)) {
521
-
522
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("Enum"));
523
-
524
- } else {
525
- rbFieldClass = rbffi_StructLayoutFieldClass;
526
- }
527
-
528
- if (!RTEST(rbFieldClass)) {
529
- rb_raise(rb_eTypeError, "invalid struct field type (%s)", rb_obj_classname(rbType));
530
- return Qnil;
531
- }
532
-
533
- rbField = rb_class_new_instance(3, fargv, rbFieldClass);
534
- } else {
535
- rbField = rbType;
536
- }
537
-
538
- store_field(builder, rbName, rbField, offset, size, alignment);
539
-
540
- return self;
541
- }
542
-
543
- static VALUE
544
- struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
545
- {
546
- StructLayoutBuilder* builder;
547
- VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
548
- VALUE rbFieldClass = Qnil, rbStructClass = Qnil;
549
- VALUE fargv[3];
550
- unsigned int size, alignment, offset;
551
- int nargs;
552
-
553
- nargs = rb_scan_args(argc, argv, "21", &rbName, &rbStructClass, &rbOffset);
554
-
555
- if (!rb_obj_is_instance_of(rbStructClass, rb_cClass) || !rb_class_inherited(rbStructClass, rbffi_StructClass)) {
556
- rb_raise(rb_eTypeError, "wrong argument type. Expected subclass of FFI::Struct");
557
- }
558
-
559
- rbType = rb_class_new_instance(1, &rbStructClass, rbffi_StructByValueClass);
560
-
561
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
562
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
563
-
564
- Data_Get_Struct(self, StructLayoutBuilder, builder);
565
-
566
- offset = calculate_offset(builder, alignment, rbOffset);
567
-
568
- fargv[0] = rbName;
569
- fargv[1] = UINT2NUM(offset);
570
- fargv[2] = rbType;
571
- rbFieldClass = rb_const_get(rbffi_StructLayoutClass, rb_intern("InlineStruct"));
572
- if (!RTEST(rbFieldClass)) {
573
- rb_raise(rb_eRuntimeError, "could not locate StructLayout::InlineStruct");
574
- return Qnil;
362
+ return retval;
575
363
  }
576
-
577
- rbField = rb_class_new_instance(3, fargv, rbFieldClass);
578
-
579
- store_field(builder, rbName, rbField, offset, size, alignment);
580
-
581
- return self;
582
- }
583
-
584
- static VALUE
585
- struct_layout_builder_add_array(int argc, VALUE* argv, VALUE self)
586
- {
587
- StructLayoutBuilder* builder;
588
- VALUE rbName = Qnil, rbType = Qnil, rbLength = Qnil, rbOffset = Qnil, rbField;
589
- VALUE fargv[3], aargv[2];
590
- unsigned int size, alignment, offset;
591
- int nargs;
592
-
593
- nargs = rb_scan_args(argc, argv, "31", &rbName, &rbType, &rbLength, &rbOffset);
594
-
595
- Data_Get_Struct(self, StructLayoutBuilder, builder);
596
-
597
- alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
598
- size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL)) * NUM2UINT(rbLength);
599
-
600
- offset = calculate_offset(builder, alignment, rbOffset);
601
-
602
- aargv[0] = rbType;
603
- aargv[1] = rbLength;
604
- fargv[0] = rbName;
605
- fargv[1] = UINT2NUM(offset);
606
- fargv[2] = rb_class_new_instance(2, aargv, rbffi_ArrayTypeClass);
607
- rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutArrayFieldClass);
608
-
609
- store_field(builder, rbName, rbField, offset, size, alignment);
610
-
611
- return self;
612
364
  }
613
365
 
614
- static inline int
615
- align(int offset, int align)
616
- {
617
- return align + ((offset - 1) & ~(align - 1));
618
- }
619
-
620
- static VALUE
621
- struct_layout_builder_build(VALUE self)
622
- {
623
- StructLayoutBuilder* builder;
624
- VALUE argv[4];
625
-
626
- Data_Get_Struct(self, StructLayoutBuilder, builder);
627
-
628
- argv[0] = builder->rbFieldNames;
629
- argv[1] = builder->rbFieldMap;
630
- argv[2] = UINT2NUM(align(builder->size, builder->alignment)); // tail padding
631
- argv[3] = UINT2NUM(builder->alignment);
632
-
633
- return rb_class_new_instance(4, argv, rbffi_StructLayoutClass);
634
- }
635
366
 
636
367
  static VALUE
637
368
  inline_array_allocate(VALUE klass)
@@ -848,10 +579,6 @@ rbffi_Struct_Init(VALUE moduleFFI)
848
579
  rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
849
580
  rb_global_variable(&rbffi_StructClass);
850
581
 
851
-
852
- StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
853
- rb_global_variable(&StructLayoutBuilderClass);
854
-
855
582
  rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
856
583
  rb_global_variable(&rbffi_StructInlineArrayClass);
857
584
 
@@ -862,6 +589,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
862
589
 
863
590
  rb_define_alloc_func(StructClass, struct_allocate);
864
591
  rb_define_method(StructClass, "initialize", struct_initialize, -1);
592
+ rb_define_method(StructClass, "order", struct_order, -1);
865
593
 
866
594
  rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
867
595
  rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
@@ -878,22 +606,7 @@ rbffi_Struct_Init(VALUE moduleFFI)
878
606
 
879
607
  rb_define_method(StructClass, "[]", struct_aref, 1);
880
608
  rb_define_method(StructClass, "[]=", struct_aset, 2);
881
-
882
-
883
-
884
- rb_define_alloc_func(StructLayoutBuilderClass, struct_layout_builder_allocate);
885
- rb_define_method(StructLayoutBuilderClass, "initialize", struct_layout_builder_initialize, 0);
886
- rb_define_method(StructLayoutBuilderClass, "build", struct_layout_builder_build, 0);
887
-
888
- rb_define_method(StructLayoutBuilderClass, "alignment", struct_layout_builder_get_alignment, 0);
889
- rb_define_method(StructLayoutBuilderClass, "alignment=", struct_layout_builder_set_alignment, 1);
890
- rb_define_method(StructLayoutBuilderClass, "size", struct_layout_builder_get_size, 0);
891
- rb_define_method(StructLayoutBuilderClass, "size=", struct_layout_builder_set_size, 1);
892
- rb_define_method(StructLayoutBuilderClass, "union=", struct_layout_builder_set_union, 1);
893
- rb_define_method(StructLayoutBuilderClass, "union?", struct_layout_builder_union_p, 0);
894
- rb_define_method(StructLayoutBuilderClass, "add_field", struct_layout_builder_add_field, -1);
895
- rb_define_method(StructLayoutBuilderClass, "add_array", struct_layout_builder_add_array, -1);
896
- rb_define_method(StructLayoutBuilderClass, "add_struct", struct_layout_builder_add_struct, -1);
609
+ rb_define_method(StructClass, "null?", struct_null_p, 0);
897
610
 
898
611
  rb_include_module(rbffi_StructInlineArrayClass, rb_mEnumerable);
899
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
+