ffi 1.2.1 → 1.3.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 (67) hide show
  1. data/README.md +10 -5
  2. data/ext/ffi_c/ArrayType.c +6 -2
  3. data/ext/ffi_c/Buffer.c +3 -1
  4. data/ext/ffi_c/Call.c +12 -21
  5. data/ext/ffi_c/FunctionInfo.c +27 -2
  6. data/ext/ffi_c/MappedType.c +1 -2
  7. data/ext/ffi_c/MemoryPointer.c +35 -4
  8. data/ext/ffi_c/Pointer.c +5 -4
  9. data/ext/ffi_c/Struct.c +125 -8
  10. data/ext/ffi_c/StructByReference.c +33 -0
  11. data/ext/ffi_c/StructByValue.c +2 -2
  12. data/ext/ffi_c/StructLayout.c +135 -1
  13. data/ext/ffi_c/Type.c +1 -0
  14. data/ext/ffi_c/extconf.rb +1 -1
  15. data/ffi.gemspec +1 -1
  16. data/lib/ffi.rb +2 -1
  17. data/lib/ffi/library.rb +2 -0
  18. data/lib/ffi/managedstruct.rb +37 -37
  19. data/lib/ffi/struct.rb +74 -1
  20. data/lib/ffi/struct_layout_builder.rb +50 -1
  21. data/lib/ffi/tools/generator.rb +2 -0
  22. data/lib/ffi/tools/generator_task.rb +1 -0
  23. data/lib/ffi/tools/types_generator.rb +2 -0
  24. data/libtest/Benchmark.c +1 -15
  25. data/libtest/BoolTest.c +2 -16
  26. data/libtest/BufferTest.c +3 -17
  27. data/libtest/ClosureTest.c +1 -15
  28. data/libtest/EnumTest.c +1 -15
  29. data/libtest/FunctionTest.c +2 -16
  30. data/libtest/GlobalVariable.c +2 -16
  31. data/libtest/LastErrorTest.c +2 -16
  32. data/libtest/NumberTest.c +1 -15
  33. data/libtest/PointerTest.c +1 -15
  34. data/libtest/ReferenceTest.c +1 -15
  35. data/libtest/StringTest.c +1 -15
  36. data/libtest/StructTest.c +1 -15
  37. data/libtest/UnionTest.c +1 -15
  38. data/libtest/VariadicTest.c +2 -16
  39. data/spec/ffi/async_callback_spec.rb +3 -14
  40. data/spec/ffi/bool_spec.rb +7 -18
  41. data/spec/ffi/buffer_spec.rb +26 -37
  42. data/spec/ffi/callback_spec.rb +96 -107
  43. data/spec/ffi/custom_param_type.rb +2 -13
  44. data/spec/ffi/custom_type_spec.rb +1 -12
  45. data/spec/ffi/dup_spec.rb +7 -18
  46. data/spec/ffi/enum_spec.rb +128 -139
  47. data/spec/ffi/errno_spec.rb +2 -13
  48. data/spec/ffi/ffi_spec.rb +4 -15
  49. data/spec/ffi/function_spec.rb +6 -17
  50. data/spec/ffi/library_spec.rb +26 -26
  51. data/spec/ffi/long_double.rb +1 -12
  52. data/spec/ffi/managed_struct_spec.rb +3 -18
  53. data/spec/ffi/number_spec.rb +32 -43
  54. data/spec/ffi/pointer_spec.rb +7 -22
  55. data/spec/ffi/rbx/memory_pointer_spec.rb +17 -17
  56. data/spec/ffi/rbx/struct_spec.rb +2 -2
  57. data/spec/ffi/spec_helper.rb +10 -12
  58. data/spec/ffi/string_spec.rb +9 -20
  59. data/spec/ffi/strptr_spec.rb +2 -13
  60. data/spec/ffi/struct_callback_spec.rb +3 -14
  61. data/spec/ffi/struct_initialize_spec.rb +3 -14
  62. data/spec/ffi/struct_packed_spec.rb +7 -18
  63. data/spec/ffi/struct_spec.rb +93 -104
  64. data/spec/ffi/typedef_spec.rb +5 -16
  65. data/spec/ffi/union_spec.rb +4 -15
  66. data/spec/ffi/variadic_spec.rb +7 -18
  67. metadata +73 -58
@@ -70,6 +70,12 @@ sbr_allocate(VALUE klass)
70
70
  return obj;
71
71
  }
72
72
 
73
+ /*
74
+ * call-seq: initialize(struc_class)
75
+ * @param [Struct] struct_calss
76
+ * @return [self]
77
+ * A new instance of StructByReference.
78
+ */
73
79
  static VALUE
74
80
  sbr_initialize(VALUE self, VALUE rbStructClass)
75
81
  {
@@ -92,6 +98,11 @@ sbr_mark(StructByReference *sbr)
92
98
  }
93
99
 
94
100
 
101
+ /*
102
+ * call-seq: struct_class
103
+ * @return [Struct]
104
+ * Get +struct_class+.
105
+ */
95
106
  static VALUE
96
107
  sbr_struct_class(VALUE self)
97
108
  {
@@ -102,12 +113,23 @@ sbr_struct_class(VALUE self)
102
113
  return sbr->rbStructClass;
103
114
  }
104
115
 
116
+ /*
117
+ * call-seq: native_type
118
+ * @return [Class]
119
+ * Always get {FFI::Type}::POINTER.
120
+ */
105
121
  static VALUE
106
122
  sbr_native_type(VALUE self)
107
123
  {
108
124
  return rb_const_get(rbffi_TypeClass, rb_intern("POINTER"));
109
125
  }
110
126
 
127
+ /*
128
+ * call-seq: to_native(value, ctx)
129
+ * @param [nil, Struct] value
130
+ * @param [nil] ctx
131
+ * @return [AbstractMemory] Pointer on +value+.
132
+ */
111
133
  static VALUE
112
134
  sbr_to_native(VALUE self, VALUE value, VALUE ctx)
113
135
  {
@@ -130,6 +152,13 @@ sbr_to_native(VALUE self, VALUE value, VALUE ctx)
130
152
  return s->rbPointer;
131
153
  }
132
154
 
155
+ /*
156
+ * call-seq: from_native(value, ctx)
157
+ * @param [AbstractMemory] value
158
+ * @param [nil] ctx
159
+ * @return [Struct]
160
+ * Create a struct from content of memory +value+.
161
+ */
133
162
  static VALUE
134
163
  sbr_from_native(VALUE self, VALUE value, VALUE ctx)
135
164
  {
@@ -144,6 +173,10 @@ sbr_from_native(VALUE self, VALUE value, VALUE ctx)
144
173
  void
145
174
  rbffi_StructByReference_Init(VALUE moduleFFI)
146
175
  {
176
+ /*
177
+ * Document-class: FFI::StructByReference
178
+ * This class includes {FFI::DataConverter} module.
179
+ */
147
180
  rbffi_StructByReferenceClass = rb_define_class_under(moduleFFI, "StructByReference", rb_cObject);
148
181
  rb_global_variable(&rbffi_StructByReferenceClass);
149
182
  rb_include_module(rbffi_StructByReferenceClass, rb_const_get(moduleFFI, rb_intern("DataConverter")));
@@ -77,9 +77,9 @@ sbv_initialize(VALUE self, VALUE rbStructClass)
77
77
  StructLayout* layout = NULL;
78
78
  VALUE rbLayout = Qnil;
79
79
 
80
- rbLayout = rb_cvar_get(rbStructClass, rb_intern("@layout"));
80
+ rbLayout = rb_ivar_get(rbStructClass, rb_intern("@layout"));
81
81
  if (!rb_obj_is_instance_of(rbLayout, rbffi_StructLayoutClass)) {
82
- rb_raise(rb_eTypeError, "wrong type in @layout cvar (expected FFI::StructLayout)");
82
+ rb_raise(rb_eTypeError, "wrong type in @layout ivar (expected FFI::StructLayout)");
83
83
  }
84
84
 
85
85
  Data_Get_Struct(rbLayout, StructLayout, layout);
@@ -78,6 +78,14 @@ struct_field_mark(StructField* f)
78
78
  rb_gc_mark(f->rbName);
79
79
  }
80
80
 
81
+ /*
82
+ * call-seq: initialize(name, offset, type)
83
+ * @param [String,Symbol] name
84
+ * @param [Fixnum] offset
85
+ * @param [FFI::Type] type
86
+ * @return [self]
87
+ * A new FFI::StructLayout::Field instance.
88
+ */
81
89
  static VALUE
82
90
  struct_field_initialize(int argc, VALUE* argv, VALUE self)
83
91
  {
@@ -126,6 +134,11 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self)
126
134
  return self;
127
135
  }
128
136
 
137
+ /*
138
+ * call-seq: offset
139
+ * @return [Numeric]
140
+ * Get the field offset.
141
+ */
129
142
  static VALUE
130
143
  struct_field_offset(VALUE self)
131
144
  {
@@ -134,6 +147,11 @@ struct_field_offset(VALUE self)
134
147
  return UINT2NUM(field->offset);
135
148
  }
136
149
 
150
+ /*
151
+ * call-seq: size
152
+ * @return [Numeric]
153
+ * Get the field size.
154
+ */
137
155
  static VALUE
138
156
  struct_field_size(VALUE self)
139
157
  {
@@ -142,6 +160,11 @@ struct_field_size(VALUE self)
142
160
  return UINT2NUM(field->type->ffiType->size);
143
161
  }
144
162
 
163
+ /*
164
+ * call-seq: alignment
165
+ * @return [Numeric]
166
+ * Get the field alignment.
167
+ */
145
168
  static VALUE
146
169
  struct_field_alignment(VALUE self)
147
170
  {
@@ -150,6 +173,11 @@ struct_field_alignment(VALUE self)
150
173
  return UINT2NUM(field->type->ffiType->alignment);
151
174
  }
152
175
 
176
+ /*
177
+ * call-seq: type
178
+ * @return [Type]
179
+ * Get the field type.
180
+ */
153
181
  static VALUE
154
182
  struct_field_type(VALUE self)
155
183
  {
@@ -159,6 +187,11 @@ struct_field_type(VALUE self)
159
187
  return field->rbType;
160
188
  }
161
189
 
190
+ /*
191
+ * call-seq: name
192
+ * @return [Symbol]
193
+ * Get the field name.
194
+ */
162
195
  static VALUE
163
196
  struct_field_name(VALUE self)
164
197
  {
@@ -167,6 +200,12 @@ struct_field_name(VALUE self)
167
200
  return field->rbName;
168
201
  }
169
202
 
203
+ /*
204
+ * call-seq: get(pointer)
205
+ * @param [AbstractMemory] pointer pointer on a {Struct}
206
+ * @return [Object]
207
+ * Get an object of type {#type} from memory pointed by +pointer+.
208
+ */
170
209
  static VALUE
171
210
  struct_field_get(VALUE self, VALUE pointer)
172
211
  {
@@ -181,6 +220,13 @@ struct_field_get(VALUE self, VALUE pointer)
181
220
  return (*f->memoryOp->get)(MEMORY(pointer), f->offset);
182
221
  }
183
222
 
223
+ /*
224
+ * call-seq: put(pointer, value)
225
+ * @param [AbstractMemory] pointer pointer on a {Struct}
226
+ * @param [Object] value this object must be a kind of {#type}
227
+ * @return [self]
228
+ * Put an object to memory pointed by +pointer+.
229
+ */
184
230
  static VALUE
185
231
  struct_field_put(VALUE self, VALUE pointer, VALUE value)
186
232
  {
@@ -197,6 +243,12 @@ struct_field_put(VALUE self, VALUE pointer, VALUE value)
197
243
  return self;
198
244
  }
199
245
 
246
+ /*
247
+ * call-seq: get(pointer)
248
+ * @param [AbstractMemory] pointer pointer on a {Struct}
249
+ * @return [Function]
250
+ * Get a {Function} from memory pointed by +pointer+.
251
+ */
200
252
  static VALUE
201
253
  function_field_get(VALUE self, VALUE pointer)
202
254
  {
@@ -207,6 +259,15 @@ function_field_get(VALUE self, VALUE pointer)
207
259
  return rbffi_Function_NewInstance(f->rbType, (*rbffi_AbstractMemoryOps.pointer->get)(MEMORY(pointer), f->offset));
208
260
  }
209
261
 
262
+ /*
263
+ * call-seq: put(pointer, proc)
264
+ * @param [AbstractMemory] pointer pointer to a {Struct}
265
+ * @param [Function, Proc] proc
266
+ * @return [Function]
267
+ * Set a {Function} to memory pointed by +pointer+ as a function.
268
+ *
269
+ * If a Proc is submitted as +proc+, it is automatically transformed to a {Function}.
270
+ */
210
271
  static VALUE
211
272
  function_field_put(VALUE self, VALUE pointer, VALUE proc)
212
273
  {
@@ -235,6 +296,12 @@ isCharArray(ArrayType* arrayType)
235
296
  || arrayType->componentType->nativeType == NATIVE_UINT8;
236
297
  }
237
298
 
299
+ /*
300
+ * call-seq: get(pointer)
301
+ * @param [AbstractMemory] pointer pointer on a {Struct}
302
+ * @return [FFI::StructLayout::CharArray, FFI::Struct::InlineArray]
303
+ * Get an array from a {Struct}.
304
+ */
238
305
  static VALUE
239
306
  array_field_get(VALUE self, VALUE pointer)
240
307
  {
@@ -252,6 +319,13 @@ array_field_get(VALUE self, VALUE pointer)
252
319
  ? rbffi_StructLayoutCharArrayClass : rbffi_StructInlineArrayClass);
253
320
  }
254
321
 
322
+ /*
323
+ * call-seq: put(pointer, value)
324
+ * @param [AbstractMemory] pointer pointer on a {Struct}
325
+ * @param [String, Array] value +value+ may be a String only if array's type is a kind of +int8+
326
+ * @return [value]
327
+ * Set an array in a {Struct}.
328
+ */
255
329
  static VALUE
256
330
  array_field_put(VALUE self, VALUE pointer, VALUE value)
257
331
  {
@@ -346,6 +420,14 @@ struct_layout_allocate(VALUE klass)
346
420
  return obj;
347
421
  }
348
422
 
423
+ /*
424
+ * call-seq: initialize(fields, size, align)
425
+ * @param [Array<StructLayout::Field>] fields
426
+ * @param [Numeric] size
427
+ * @param [Numeric] align
428
+ * @return [self]
429
+ * A new StructLayout instance.
430
+ */
349
431
  static VALUE
350
432
  struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
351
433
  {
@@ -411,6 +493,12 @@ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
411
493
  return self;
412
494
  }
413
495
 
496
+ /*
497
+ * call-seq: [](field)
498
+ * @param [Symbol] field
499
+ * @return [StructLayout::Field]
500
+ * Get a field from the layout.
501
+ */
414
502
  static VALUE
415
503
  struct_layout_union_bang(VALUE self)
416
504
  {
@@ -455,6 +543,11 @@ struct_layout_aref(VALUE self, VALUE field)
455
543
  return rb_hash_aref(layout->rbFieldMap, field);
456
544
  }
457
545
 
546
+ /*
547
+ * call-seq: fields
548
+ * @return [Array<StructLayout::Field>]
549
+ * Get fields list.
550
+ */
458
551
  static VALUE
459
552
  struct_layout_fields(VALUE self)
460
553
  {
@@ -465,6 +558,11 @@ struct_layout_fields(VALUE self)
465
558
  return rb_ary_dup(layout->rbFields);
466
559
  }
467
560
 
561
+ /*
562
+ * call-seq: members
563
+ * @return [Array<Symbol>]
564
+ * Get list of field names.
565
+ */
468
566
  static VALUE
469
567
  struct_layout_members(VALUE self)
470
568
  {
@@ -475,6 +573,11 @@ struct_layout_members(VALUE self)
475
573
  return rb_ary_dup(layout->rbFieldNames);
476
574
  }
477
575
 
576
+ /*
577
+ * call-seq: to_a
578
+ * @return [Array<StructLayout::Field>]
579
+ * Get an array of fields.
580
+ */
478
581
  static VALUE
479
582
  struct_layout_to_a(VALUE self)
480
583
  {
@@ -507,24 +610,55 @@ struct_layout_free(StructLayout *layout)
507
610
  void
508
611
  rbffi_StructLayout_Init(VALUE moduleFFI)
509
612
  {
510
- rbffi_StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rbffi_TypeClass);
613
+ VALUE ffi_Type = rbffi_TypeClass;
614
+
615
+ /*
616
+ * Document-class: FFI::StructLayout < FFI::Type
617
+ *
618
+ * This class aims at defining a struct layout.
619
+ */
620
+ rbffi_StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", ffi_Type);
511
621
  rb_global_variable(&rbffi_StructLayoutClass);
512
622
 
623
+ /*
624
+ * Document-class: FFI::StructLayout::Field
625
+ * A field in a {StructLayout}.
626
+ */
513
627
  rbffi_StructLayoutFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Field", rb_cObject);
514
628
  rb_global_variable(&rbffi_StructLayoutFieldClass);
515
629
 
630
+ /*
631
+ * Document-class: FFI::StructLayout::Number
632
+ * A numeric {Field} in a {StructLayout}.
633
+ */
516
634
  rbffi_StructLayoutNumberFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Number", rbffi_StructLayoutFieldClass);
517
635
  rb_global_variable(&rbffi_StructLayoutNumberFieldClass);
518
636
 
637
+ /*
638
+ * Document-class: FFI::StructLayout::String
639
+ * A string {Field} in a {StructLayout}.
640
+ */
519
641
  rbffi_StructLayoutStringFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "String", rbffi_StructLayoutFieldClass);
520
642
  rb_global_variable(&rbffi_StructLayoutStringFieldClass);
521
643
 
644
+ /*
645
+ * Document-class: FFI::StructLayout::Pointer
646
+ * A pointer {Field} in a {StructLayout}.
647
+ */
522
648
  rbffi_StructLayoutPointerFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Pointer", rbffi_StructLayoutFieldClass);
523
649
  rb_global_variable(&rbffi_StructLayoutPointerFieldClass);
524
650
 
651
+ /*
652
+ * Document-class: FFI::StructLayout::Function
653
+ * A function pointer {Field} in a {StructLayout}.
654
+ */
525
655
  rbffi_StructLayoutFunctionFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Function", rbffi_StructLayoutFieldClass);
526
656
  rb_global_variable(&rbffi_StructLayoutFunctionFieldClass);
527
657
 
658
+ /*
659
+ * Document-class: FFI::StructLayout::Array
660
+ * An array {Field} in a {StructLayout}.
661
+ */
528
662
  rbffi_StructLayoutArrayFieldClass = rb_define_class_under(rbffi_StructLayoutClass, "Array", rbffi_StructLayoutFieldClass);
529
663
  rb_global_variable(&rbffi_StructLayoutArrayFieldClass);
530
664
 
@@ -100,6 +100,7 @@ type_size(VALUE self)
100
100
  /*
101
101
  * call-seq: type.alignment
102
102
  * @return [Fixnum]
103
+ * Get Type alignment.
103
104
  */
104
105
  static VALUE
105
106
  type_alignment(VALUE self)
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
3
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
4
4
  require 'mkmf'
5
5
  require 'rbconfig'
6
6
  dir_config("ffi_c")
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ffi'
3
- s.version = '1.2.1'
3
+ s.version = '1.3.0'
4
4
  s.author = 'Wayne Meissner'
5
5
  s.email = 'wmeissner@gmail.com'
6
6
  s.homepage = 'http://wiki.github.com/ffi/ffi'
data/lib/ffi.rb CHANGED
@@ -1,4 +1,5 @@
1
- if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
1
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
2
+ Object.send(:remove_const, :FFI) if defined?(::FFI)
2
3
  begin
3
4
  if RUBY_VERSION =~ /1.8/
4
5
  require '1.8/ffi_c'
@@ -84,6 +84,8 @@ module FFI
84
84
  # @raise {LoadError} if a library cannot be opened
85
85
  # Load native libraries.
86
86
  def ffi_lib(*names)
87
+ raise LoadError.new("library names list must not be empty") if names.empty?
88
+
87
89
  lib_flags = defined?(@ffi_lib_flags) ? @ffi_lib_flags : FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_LOCAL
88
90
  ffi_libs = names.map do |name|
89
91
 
@@ -1,50 +1,50 @@
1
1
  module FFI
2
2
  #
3
- # FFI::ManagedStruct allows custom garbage-collection of your FFI::Structs.
4
- #
5
- # The typical use case would be when interacting with a library
6
- # that has a nontrivial memory management design, such as a linked
7
- # list or a binary tree.
8
- #
9
- # When the Struct instance is garbage collected, FFI::ManagedStruct will
10
- # invoke the class's release() method during object finalization.
11
- #
12
- # Example usage:
13
- # module MyLibrary
14
- # ffi_lib "libmylibrary"
15
- # attach_function :new_dlist, [], :pointer
16
- # attach_function :destroy_dlist, [:pointer], :void
3
+ # FFI::ManagedStruct allows custom garbage-collection of your FFI::Structs.
4
+ #
5
+ # The typical use case would be when interacting with a library
6
+ # that has a nontrivial memory management design, such as a linked
7
+ # list or a binary tree.
8
+ #
9
+ # When the {Struct} instance is garbage collected, FFI::ManagedStruct will
10
+ # invoke the class's release() method during object finalization.
11
+ #
12
+ # @example Example usage:
13
+ # module MyLibrary
14
+ # ffi_lib "libmylibrary"
15
+ # attach_function :new_dlist, [], :pointer
16
+ # attach_function :destroy_dlist, [:pointer], :void
17
+ # end
18
+ #
19
+ # class DoublyLinkedList < FFI::ManagedStruct
20
+ # @@@
21
+ # struct do |s|
22
+ # s.name 'struct dlist'
23
+ # s.include 'dlist.h'
24
+ # s.field :head, :pointer
25
+ # s.field :tail, :pointer
17
26
  # end
27
+ # @@@
18
28
  #
19
- # class DoublyLinkedList < FFI::ManagedStruct
20
- # @@@
21
- # struct do |s|
22
- # s.name 'struct dlist'
23
- # s.include 'dlist.h'
24
- # s.field :head, :pointer
25
- # s.field :tail, :pointer
26
- # end
27
- # @@@
28
- #
29
- # def self.release ptr
30
- # MyLibrary.destroy_dlist(ptr)
31
- # end
29
+ # def self.release ptr
30
+ # MyLibrary.destroy_dlist(ptr)
32
31
  # end
32
+ # end
33
33
  #
34
- # begin
35
- # ptr = DoublyLinkedList.new(MyLibrary.new_dlist)
36
- # # do something with the list
37
- # end
38
- # # struct is out of scope, and will be GC'd using DoublyLinkedList#release
34
+ # begin
35
+ # ptr = DoublyLinkedList.new(MyLibrary.new_dlist)
36
+ # # do something with the list
37
+ # end
38
+ # # struct is out of scope, and will be GC'd using DoublyLinkedList#release
39
39
  #
40
40
  #
41
41
  class ManagedStruct < FFI::Struct
42
42
 
43
- # call-seq:
44
- # ManagedStruct.new(pointer)
45
- # ManagedStruct.new
46
- #
47
- # When passed a pointer, create a new ManagedStruct which will invoke the class method release() on
43
+ # @overload initialize(pointer)
44
+ # @param [Pointer] pointer
45
+ # Create a new ManagedStruct which will invoke the class method #release on
46
+ # @overload initialize
47
+ # A new instance of FFI::ManagedStruct.
48
48
  def initialize(pointer=nil)
49
49
  raise NoMethodError, "release() not implemented for class #{self}" unless self.class.respond_to? :release
50
50
  raise ArgumentError, "Must supply a pointer to memory for the Struct" unless pointer