ffi 1.0.5 → 1.0.6
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/Rakefile +1 -1
- data/ext/ffi_c/Struct.c +36 -1
- data/ext/ffi_c/Struct.h +9 -0
- data/ext/ffi_c/StructLayout.c +23 -1
- metadata +27 -9
data/Rakefile
CHANGED
data/ext/ffi_c/Struct.c
CHANGED
@@ -52,9 +52,11 @@ typedef struct InlineArray_ {
|
|
52
52
|
|
53
53
|
|
54
54
|
static void struct_mark(Struct *);
|
55
|
+
static void struct_free(Struct *);
|
55
56
|
static VALUE struct_class_layout(VALUE klass);
|
56
57
|
static void struct_malloc(Struct* s);
|
57
58
|
static void inline_array_mark(InlineArray *);
|
59
|
+
static void store_reference_value(StructField* f, Struct* s, VALUE value);
|
58
60
|
|
59
61
|
VALUE rbffi_StructClass = Qnil;
|
60
62
|
|
@@ -74,7 +76,7 @@ static VALUE
|
|
74
76
|
struct_allocate(VALUE klass)
|
75
77
|
{
|
76
78
|
Struct* s;
|
77
|
-
VALUE obj = Data_Make_Struct(klass, Struct, struct_mark,
|
79
|
+
VALUE obj = Data_Make_Struct(klass, Struct, struct_mark, struct_free, s);
|
78
80
|
|
79
81
|
s->rbPointer = Qnil;
|
80
82
|
s->rbLayout = Qnil;
|
@@ -183,8 +185,37 @@ struct_mark(Struct *s)
|
|
183
185
|
{
|
184
186
|
rb_gc_mark(s->rbPointer);
|
185
187
|
rb_gc_mark(s->rbLayout);
|
188
|
+
if (s->rbReferences != NULL) {
|
189
|
+
rb_gc_mark_locations(&s->rbReferences[0], &s->rbReferences[s->layout->referenceFieldCount]);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
static void
|
194
|
+
struct_free(Struct* s)
|
195
|
+
{
|
196
|
+
xfree(s->rbReferences);
|
186
197
|
}
|
187
198
|
|
199
|
+
|
200
|
+
static void
|
201
|
+
store_reference_value(StructField* f, Struct* s, VALUE value)
|
202
|
+
{
|
203
|
+
if (unlikely(f->referenceIndex == -1)) {
|
204
|
+
rb_raise(rb_eRuntimeError, "put_reference_value called for non-reference type");
|
205
|
+
return;
|
206
|
+
}
|
207
|
+
if (s->rbReferences == NULL) {
|
208
|
+
int i;
|
209
|
+
s->rbReferences = ALLOC_N(VALUE, s->layout->referenceFieldCount);
|
210
|
+
for (i = 0; i < s->layout->referenceFieldCount; ++i) {
|
211
|
+
s->rbReferences[i] = Qnil;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
s->rbReferences[f->referenceIndex] = value;
|
216
|
+
}
|
217
|
+
|
218
|
+
|
188
219
|
static VALUE
|
189
220
|
struct_field(Struct* s, VALUE fieldName)
|
190
221
|
{
|
@@ -255,6 +286,10 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
|
255
286
|
argv[1] = value;
|
256
287
|
rb_funcall2(rbField, id_put, 2, argv);
|
257
288
|
}
|
289
|
+
|
290
|
+
if (f->referenceRequired) {
|
291
|
+
store_reference_value(f, s, value);
|
292
|
+
}
|
258
293
|
|
259
294
|
return value;
|
260
295
|
}
|
data/ext/ffi_c/Struct.h
CHANGED
@@ -44,6 +44,9 @@ extern "C" {
|
|
44
44
|
Type* type;
|
45
45
|
unsigned int offset;
|
46
46
|
|
47
|
+
int referenceIndex;
|
48
|
+
|
49
|
+
bool referenceRequired;
|
47
50
|
VALUE rbType;
|
48
51
|
VALUE rbName;
|
49
52
|
|
@@ -61,6 +64,10 @@ extern "C" {
|
|
61
64
|
int align;
|
62
65
|
ffi_type** ffiTypes;
|
63
66
|
struct st_table* fieldSymbolTable;
|
67
|
+
|
68
|
+
/** The number of reference tracking fields in this struct */
|
69
|
+
int referenceFieldCount;
|
70
|
+
|
64
71
|
VALUE rbFieldNames;
|
65
72
|
VALUE rbFieldMap;
|
66
73
|
VALUE rbFields;
|
@@ -69,6 +76,8 @@ extern "C" {
|
|
69
76
|
struct Struct_ {
|
70
77
|
StructLayout* layout;
|
71
78
|
AbstractMemory* pointer;
|
79
|
+
VALUE* rbReferences;
|
80
|
+
|
72
81
|
VALUE rbLayout;
|
73
82
|
VALUE rbPointer;
|
74
83
|
};
|
data/ext/ffi_c/StructLayout.c
CHANGED
@@ -36,6 +36,7 @@
|
|
36
36
|
#include "Struct.h"
|
37
37
|
#include "StructByValue.h"
|
38
38
|
#include "ArrayType.h"
|
39
|
+
#include "MappedType.h"
|
39
40
|
|
40
41
|
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
41
42
|
|
@@ -99,7 +100,23 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self)
|
|
99
100
|
field->rbType = rbType;
|
100
101
|
Data_Get_Struct(field->rbType, Type, field->type);
|
101
102
|
field->memoryOp = get_memory_op(field->type);
|
102
|
-
|
103
|
+
field->referenceIndex = -1;
|
104
|
+
|
105
|
+
switch (field->type->nativeType == NATIVE_MAPPED ? ((MappedType *) field->type)->type->nativeType : field->type->nativeType) {
|
106
|
+
case NATIVE_FUNCTION:
|
107
|
+
case NATIVE_CALLBACK:
|
108
|
+
case NATIVE_POINTER:
|
109
|
+
field->referenceRequired = true;
|
110
|
+
break;
|
111
|
+
|
112
|
+
default:
|
113
|
+
field->referenceRequired = (rb_respond_to(self, rb_intern("reference_required?"))
|
114
|
+
&& RTEST(rb_funcall2(self, rb_intern("reference_required?"), 0, NULL)))
|
115
|
+
|| (rb_respond_to(rbType, rb_intern("reference_required?"))
|
116
|
+
&& RTEST(rb_funcall2(rbType, rb_intern("reference_required?"), 0, NULL)));
|
117
|
+
break;
|
118
|
+
}
|
119
|
+
|
103
120
|
return self;
|
104
121
|
}
|
105
122
|
|
@@ -339,6 +356,7 @@ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
|
|
339
356
|
layout->fields = xcalloc(layout->fieldCount, sizeof(StructField *));
|
340
357
|
layout->ffiTypes = xcalloc(layout->fieldCount + 1, sizeof(ffi_type *));
|
341
358
|
layout->rbFields = rb_ary_new2(layout->fieldCount);
|
359
|
+
layout->referenceFieldCount = 0;
|
342
360
|
layout->base.ffiType->elements = layout->ffiTypes;
|
343
361
|
layout->base.ffiType->size = layout->size;
|
344
362
|
layout->base.ffiType->alignment = layout->align;
|
@@ -367,6 +385,10 @@ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align)
|
|
367
385
|
rb_raise(rb_eTypeError, "type of field %d has zero size", i);
|
368
386
|
}
|
369
387
|
|
388
|
+
if (field->referenceRequired) {
|
389
|
+
field->referenceIndex = layout->referenceFieldCount++;
|
390
|
+
}
|
391
|
+
|
370
392
|
layout->ffiTypes[i] = ftype;
|
371
393
|
st_insert(layout->fieldSymbolTable, rbName, rbField);
|
372
394
|
rb_hash_aset(layout->rbFieldMap, rbName, rbField);
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 6
|
10
|
+
version: 1.0.6
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Wayne Meissner
|
@@ -9,19 +15,25 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2011-
|
18
|
+
date: 2011-02-21 00:00:00 +10:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: rake
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 49
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 8
|
33
|
+
- 7
|
23
34
|
version: 0.8.7
|
24
|
-
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
25
37
|
description: |-
|
26
38
|
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
27
39
|
libraries, binding functions within them, and calling those functions
|
@@ -422,21 +434,27 @@ require_paths:
|
|
422
434
|
- lib
|
423
435
|
- ext
|
424
436
|
required_ruby_version: !ruby/object:Gem::Requirement
|
437
|
+
none: false
|
425
438
|
requirements:
|
426
439
|
- - ">="
|
427
440
|
- !ruby/object:Gem::Version
|
441
|
+
hash: 3
|
442
|
+
segments:
|
443
|
+
- 0
|
428
444
|
version: "0"
|
429
|
-
version:
|
430
445
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
446
|
+
none: false
|
431
447
|
requirements:
|
432
448
|
- - ">="
|
433
449
|
- !ruby/object:Gem::Version
|
450
|
+
hash: 3
|
451
|
+
segments:
|
452
|
+
- 0
|
434
453
|
version: "0"
|
435
|
-
version:
|
436
454
|
requirements: []
|
437
455
|
|
438
456
|
rubyforge_project: ffi
|
439
|
-
rubygems_version: 1.3.
|
457
|
+
rubygems_version: 1.3.7
|
440
458
|
signing_key:
|
441
459
|
specification_version: 3
|
442
460
|
summary: Ruby-FFI is a ruby extension for programmatically loading dynamic libraries, binding functions within them, and calling those functions from Ruby code
|