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.
- data/README.md +10 -5
- data/ext/ffi_c/ArrayType.c +6 -2
- data/ext/ffi_c/Buffer.c +3 -1
- data/ext/ffi_c/Call.c +12 -21
- data/ext/ffi_c/FunctionInfo.c +27 -2
- data/ext/ffi_c/MappedType.c +1 -2
- data/ext/ffi_c/MemoryPointer.c +35 -4
- data/ext/ffi_c/Pointer.c +5 -4
- data/ext/ffi_c/Struct.c +125 -8
- data/ext/ffi_c/StructByReference.c +33 -0
- data/ext/ffi_c/StructByValue.c +2 -2
- data/ext/ffi_c/StructLayout.c +135 -1
- data/ext/ffi_c/Type.c +1 -0
- data/ext/ffi_c/extconf.rb +1 -1
- data/ffi.gemspec +1 -1
- data/lib/ffi.rb +2 -1
- data/lib/ffi/library.rb +2 -0
- data/lib/ffi/managedstruct.rb +37 -37
- data/lib/ffi/struct.rb +74 -1
- data/lib/ffi/struct_layout_builder.rb +50 -1
- data/lib/ffi/tools/generator.rb +2 -0
- data/lib/ffi/tools/generator_task.rb +1 -0
- data/lib/ffi/tools/types_generator.rb +2 -0
- data/libtest/Benchmark.c +1 -15
- data/libtest/BoolTest.c +2 -16
- data/libtest/BufferTest.c +3 -17
- data/libtest/ClosureTest.c +1 -15
- data/libtest/EnumTest.c +1 -15
- data/libtest/FunctionTest.c +2 -16
- data/libtest/GlobalVariable.c +2 -16
- data/libtest/LastErrorTest.c +2 -16
- data/libtest/NumberTest.c +1 -15
- data/libtest/PointerTest.c +1 -15
- data/libtest/ReferenceTest.c +1 -15
- data/libtest/StringTest.c +1 -15
- data/libtest/StructTest.c +1 -15
- data/libtest/UnionTest.c +1 -15
- data/libtest/VariadicTest.c +2 -16
- data/spec/ffi/async_callback_spec.rb +3 -14
- data/spec/ffi/bool_spec.rb +7 -18
- data/spec/ffi/buffer_spec.rb +26 -37
- data/spec/ffi/callback_spec.rb +96 -107
- data/spec/ffi/custom_param_type.rb +2 -13
- data/spec/ffi/custom_type_spec.rb +1 -12
- data/spec/ffi/dup_spec.rb +7 -18
- data/spec/ffi/enum_spec.rb +128 -139
- data/spec/ffi/errno_spec.rb +2 -13
- data/spec/ffi/ffi_spec.rb +4 -15
- data/spec/ffi/function_spec.rb +6 -17
- data/spec/ffi/library_spec.rb +26 -26
- data/spec/ffi/long_double.rb +1 -12
- data/spec/ffi/managed_struct_spec.rb +3 -18
- data/spec/ffi/number_spec.rb +32 -43
- data/spec/ffi/pointer_spec.rb +7 -22
- data/spec/ffi/rbx/memory_pointer_spec.rb +17 -17
- data/spec/ffi/rbx/struct_spec.rb +2 -2
- data/spec/ffi/spec_helper.rb +10 -12
- data/spec/ffi/string_spec.rb +9 -20
- data/spec/ffi/strptr_spec.rb +2 -13
- data/spec/ffi/struct_callback_spec.rb +3 -14
- data/spec/ffi/struct_initialize_spec.rb +3 -14
- data/spec/ffi/struct_packed_spec.rb +7 -18
- data/spec/ffi/struct_spec.rb +93 -104
- data/spec/ffi/typedef_spec.rb +5 -16
- data/spec/ffi/union_spec.rb +4 -15
- data/spec/ffi/variadic_spec.rb +7 -18
- 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")));
|
data/ext/ffi_c/StructByValue.c
CHANGED
@@ -77,9 +77,9 @@ sbv_initialize(VALUE self, VALUE rbStructClass)
|
|
77
77
|
StructLayout* layout = NULL;
|
78
78
|
VALUE rbLayout = Qnil;
|
79
79
|
|
80
|
-
rbLayout =
|
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
|
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);
|
data/ext/ffi_c/StructLayout.c
CHANGED
@@ -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
|
-
|
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
|
|
data/ext/ffi_c/Type.c
CHANGED
data/ext/ffi_c/extconf.rb
CHANGED
data/ffi.gemspec
CHANGED
data/lib/ffi.rb
CHANGED
data/lib/ffi/library.rb
CHANGED
@@ -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
|
|
data/lib/ffi/managedstruct.rb
CHANGED
@@ -1,50 +1,50 @@
|
|
1
1
|
module FFI
|
2
2
|
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
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
|
-
#
|
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
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
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
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
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
|