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.
- data/History.txt +109 -0
- data/LICENSE +10 -21
- data/README.rdoc +1 -0
- data/Rakefile +3 -2
- data/ext/ffi_c/AbstractMemory.c +56 -38
- data/ext/ffi_c/AbstractMemory.h +15 -22
- data/ext/ffi_c/Buffer.c +61 -22
- data/ext/ffi_c/Call.c +55 -543
- data/ext/ffi_c/Call.h +1 -1
- data/ext/ffi_c/DataConverter.c +62 -0
- data/ext/ffi_c/DynamicLibrary.c +21 -1
- data/ext/ffi_c/Function.c +255 -32
- data/ext/ffi_c/MappedType.c +146 -0
- data/ext/ffi_c/MappedType.h +57 -0
- data/ext/ffi_c/MemoryPointer.c +12 -33
- data/ext/ffi_c/Platform.c +2 -0
- data/ext/ffi_c/Pointer.c +66 -28
- data/ext/ffi_c/Struct.c +106 -318
- data/ext/ffi_c/Struct.h +6 -0
- data/ext/ffi_c/StructByReference.c +150 -0
- data/ext/ffi_c/StructByReference.h +50 -0
- data/ext/ffi_c/StructLayout.c +25 -14
- data/ext/ffi_c/Type.c +39 -68
- data/ext/ffi_c/Type.h +12 -22
- data/ext/ffi_c/Types.c +21 -6
- data/ext/ffi_c/Types.h +7 -7
- data/ext/ffi_c/Variadic.c +21 -17
- data/ext/ffi_c/extconf.rb +4 -0
- data/ext/ffi_c/ffi.c +8 -2
- data/ext/ffi_c/libffi/configure +1 -1
- data/ext/ffi_c/libffi.gnu.mk +1 -1
- data/ext/ffi_c/libffi.mk +1 -1
- data/ext/ffi_c/rbffi.h +1 -0
- data/gen/Rakefile +4 -2
- data/lib/ffi/autopointer.rb +23 -22
- data/lib/ffi/enum.rb +36 -21
- data/lib/ffi/errno.rb +20 -0
- data/lib/ffi/ffi.rb +13 -79
- data/lib/ffi/io.rb +12 -20
- data/lib/ffi/library.rb +110 -93
- data/lib/ffi/managedstruct.rb +1 -1
- data/lib/ffi/memorypointer.rb +15 -21
- data/lib/ffi/platform.rb +24 -28
- data/lib/ffi/pointer.rb +14 -21
- data/lib/ffi/struct.rb +100 -51
- data/lib/ffi/struct_layout_builder.rb +158 -0
- data/lib/ffi/types.rb +99 -128
- data/lib/ffi/union.rb +20 -0
- data/lib/ffi/variadic.rb +33 -22
- data/spec/ffi/async_callback_spec.rb +23 -0
- data/spec/ffi/callback_spec.rb +62 -0
- data/spec/ffi/custom_param_type.rb +31 -0
- data/spec/ffi/custom_type_spec.rb +73 -0
- data/spec/ffi/enum_spec.rb +19 -0
- data/spec/ffi/ffi_spec.rb +24 -0
- data/spec/ffi/pointer_spec.rb +15 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +7 -1
- data/spec/ffi/strptr_spec.rb +36 -0
- data/spec/ffi/struct_packed_spec.rb +46 -0
- data/spec/ffi/struct_spec.rb +39 -7
- data/spec/ffi/typedef_spec.rb +14 -0
- data/tasks/ann.rake +80 -0
- data/tasks/extension.rake +25 -0
- data/tasks/gem.rake +200 -0
- data/tasks/git.rake +41 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +301 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +64 -11
- data/ext/ffi_c/AutoPointer.c +0 -60
- 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
|
|
73
|
-
static void
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
339
|
+
struct_null_p(VALUE self)
|
|
347
340
|
{
|
|
348
|
-
|
|
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,
|
|
364
|
-
builder->isUnion = RTEST(rbUnion);
|
|
343
|
+
Data_Get_Struct(self, Struct, s);
|
|
365
344
|
|
|
366
|
-
return
|
|
345
|
+
return s->pointer->address == NULL ? Qtrue : Qfalse;
|
|
367
346
|
}
|
|
368
347
|
|
|
369
348
|
static VALUE
|
|
370
|
-
|
|
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
|
-
|
|
386
|
-
rb_hash_aset(builder->rbFieldMap, rbName, rbField);
|
|
387
|
-
|
|
388
|
-
builder->alignment = MAX(builder->alignment, alignment);
|
|
351
|
+
Struct* s;
|
|
389
352
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
|