ffi 0.4.0 → 0.5.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.rdoc +15 -15
- data/Rakefile +57 -8
- data/ext/ffi_c/AbstractMemory.c +101 -24
- data/ext/ffi_c/AbstractMemory.h +98 -6
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +1 -0
- data/ext/ffi_c/Buffer.c +59 -43
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +3 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +30 -6
- data/ext/ffi_c/MemoryPointer.c +50 -28
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Pointer.c +73 -13
- data/ext/ffi_c/Pointer.h +31 -7
- data/ext/ffi_c/Struct.c +517 -224
- data/ext/ffi_c/Struct.h +60 -6
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +121 -22
- data/ext/ffi_c/Type.h +37 -8
- data/ext/ffi_c/Types.c +46 -61
- data/ext/ffi_c/Types.h +38 -7
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +53 -3
- data/ext/ffi_c/extconf.rb +6 -7
- data/ext/ffi_c/ffi.c +45 -39
- data/ext/ffi_c/libffi.darwin.mk +2 -2
- data/ext/ffi_c/rbffi.h +3 -0
- data/lib/ffi/ffi.rb +7 -4
- data/lib/ffi/library.rb +34 -59
- data/lib/ffi/platform.rb +14 -4
- data/lib/ffi/struct.rb +110 -281
- data/lib/ffi/union.rb +4 -9
- data/lib/ffi/variadic.rb +1 -6
- data/spec/ffi/buffer_spec.rb +6 -0
- data/spec/ffi/callback_spec.rb +34 -3
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +56 -52
- data/spec/ffi/pointer_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +26 -3
- data/spec/ffi/struct_spec.rb +56 -3
- metadata +42 -11
- data/ext/ffi_c/Callback.c +0 -374
- data/ext/ffi_c/Callback.h +0 -47
- data/ext/ffi_c/Invoker.c +0 -962
- data/ext/ffi_c/NullPointer.c +0 -143
data/ext/ffi_c/Pointer.h
CHANGED
@@ -1,6 +1,33 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
*
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
10
|
+
* list of conditions and the following disclaimer.
|
11
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
* * The name of the author or authors may not be used to endorse or promote
|
15
|
+
* products derived from this software without specific prior written permission.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*/
|
28
|
+
|
29
|
+
#ifndef RBFFI_POINTER_H
|
30
|
+
#define RBFFI_POINTER_H
|
4
31
|
|
5
32
|
#ifdef __cplusplus
|
6
33
|
extern "C" {
|
@@ -9,17 +36,14 @@ extern "C" {
|
|
9
36
|
#include "AbstractMemory.h"
|
10
37
|
|
11
38
|
extern void rbffi_Pointer_Init(VALUE moduleFFI);
|
12
|
-
extern void rbffi_NullPointer_Init(VALUE moduleFFI);
|
13
39
|
extern VALUE rbffi_Pointer_NewInstance(void* addr);
|
14
40
|
extern VALUE rbffi_PointerClass;
|
15
|
-
extern VALUE rbffi_NullPointerClass;
|
16
41
|
extern VALUE rbffi_NullPointerSingleton;
|
17
|
-
extern MemoryOps rbffi_NullPointerOps;
|
18
42
|
|
19
43
|
|
20
44
|
#ifdef __cplusplus
|
21
45
|
}
|
22
46
|
#endif
|
23
47
|
|
24
|
-
#endif /*
|
48
|
+
#endif /* RBFFI_POINTER_H */
|
25
49
|
|
data/ext/ffi_c/Struct.c
CHANGED
@@ -1,4 +1,35 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
|
4
|
+
*
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
11
|
+
* list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
* * The name of the author or authors may not be used to endorse or promote
|
16
|
+
* products derived from this software without specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
*/
|
29
|
+
|
1
30
|
#include <sys/types.h>
|
31
|
+
|
32
|
+
#include "Function.h"
|
2
33
|
#include <sys/param.h>
|
3
34
|
#include <stdint.h>
|
4
35
|
#include <stdbool.h>
|
@@ -8,117 +39,46 @@
|
|
8
39
|
#include "AbstractMemory.h"
|
9
40
|
#include "Pointer.h"
|
10
41
|
#include "MemoryPointer.h"
|
42
|
+
#include "Function.h"
|
11
43
|
#include "Types.h"
|
12
44
|
#include "Struct.h"
|
45
|
+
#include "StructByValue.h"
|
46
|
+
#include "ArrayType.h"
|
13
47
|
|
14
|
-
|
15
|
-
unsigned int type;
|
16
|
-
unsigned int offset;
|
17
|
-
unsigned int size;
|
18
|
-
unsigned int align;
|
19
|
-
} StructField;
|
20
|
-
|
21
|
-
typedef struct StructLayout {
|
22
|
-
VALUE rbFields;
|
23
|
-
unsigned int fieldCount;
|
24
|
-
int size;
|
25
|
-
int align;
|
26
|
-
} StructLayout;
|
48
|
+
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
27
49
|
|
28
50
|
typedef struct StructLayoutBuilder {
|
29
|
-
|
51
|
+
VALUE rbFieldNames;
|
52
|
+
VALUE rbFieldMap;
|
53
|
+
unsigned int size;
|
54
|
+
unsigned int alignment;
|
55
|
+
bool isUnion;
|
30
56
|
} StructLayoutBuilder;
|
31
57
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
VALUE rbffi_StructClass = Qnil;
|
37
|
-
static VALUE StructLayoutClass = Qnil;
|
38
|
-
static VALUE StructFieldClass = Qnil, StructLayoutBuilderClass = Qnil;
|
39
|
-
static ID pointer_var_id = 0, layout_var_id = 0, SIZE_ID, ALIGN_ID, TYPE_ID;
|
40
|
-
static ID get_id = 0, put_id = 0, to_ptr = 0, to_s = 0, layout_id = 0;
|
41
|
-
|
42
|
-
static VALUE
|
43
|
-
struct_field_allocate(VALUE klass)
|
44
|
-
{
|
45
|
-
StructField* field;
|
46
|
-
return Data_Make_Struct(klass, StructField, NULL, -1, field);
|
47
|
-
}
|
58
|
+
typedef struct InlineArray_ {
|
59
|
+
VALUE rbMemory;
|
60
|
+
VALUE rbField;
|
48
61
|
|
49
|
-
|
50
|
-
struct_field_initialize(int argc, VALUE* argv, VALUE self)
|
51
|
-
{
|
52
|
-
VALUE offset = Qnil, info = Qnil;
|
62
|
+
AbstractMemory* memory;
|
53
63
|
StructField* field;
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
nargs = rb_scan_args(argc, argv, "11", &offset, &info);
|
59
|
-
|
60
|
-
field->offset = NUM2UINT(offset);
|
61
|
-
if (rb_const_defined(CLASS_OF(self), TYPE_ID)) {
|
62
|
-
field->type = NUM2UINT(rb_const_get(CLASS_OF(self), TYPE_ID));
|
63
|
-
} else {
|
64
|
-
field->type = ~0;
|
65
|
-
}
|
66
|
-
|
67
|
-
#ifdef notyet
|
68
|
-
field->size = NUM2UINT(rb_const_get(klass, SIZE_ID));
|
69
|
-
field->align = NUM2UINT(rb_const_get(klass, ALIGN_ID));
|
70
|
-
#endif
|
71
|
-
rb_iv_set(self, "@off", offset);
|
72
|
-
rb_iv_set(self, "@info", info);
|
73
|
-
|
74
|
-
return self;
|
75
|
-
}
|
64
|
+
MemoryOp *op;
|
65
|
+
Type* componentType;
|
66
|
+
} InlineArray;
|
76
67
|
|
77
|
-
static VALUE
|
78
|
-
struct_field_offset(VALUE self)
|
79
|
-
{
|
80
|
-
StructField* field;
|
81
|
-
Data_Get_Struct(self, StructField, field);
|
82
|
-
return UINT2NUM(field->offset);
|
83
|
-
}
|
84
68
|
|
85
|
-
static
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
MemoryOp* op;
|
90
|
-
AbstractMemory* memory = MEMORY(pointer);
|
91
|
-
|
92
|
-
Data_Get_Struct(self, StructField, f);
|
93
|
-
op = ptr_get_op(memory, f->type);
|
94
|
-
if (op == NULL) {
|
95
|
-
VALUE name = rb_class_name(CLASS_OF(self));
|
96
|
-
rb_raise(rb_eArgError, "get not supported for %s", StringValueCStr(name));
|
97
|
-
return Qnil;
|
98
|
-
}
|
69
|
+
static void struct_mark(Struct *);
|
70
|
+
static void struct_layout_builder_mark(StructLayoutBuilder *);
|
71
|
+
static void struct_layout_builder_free(StructLayoutBuilder *);
|
72
|
+
static void inline_array_mark(InlineArray *);
|
99
73
|
|
100
|
-
|
101
|
-
}
|
74
|
+
static inline int align(int offset, int align);
|
102
75
|
|
103
|
-
|
104
|
-
|
105
|
-
{
|
106
|
-
StructField* f;
|
107
|
-
MemoryOp* op;
|
108
|
-
AbstractMemory* memory = MEMORY(pointer);
|
76
|
+
VALUE rbffi_StructClass = Qnil;
|
77
|
+
static VALUE StructLayoutBuilderClass = Qnil;
|
109
78
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
VALUE name = rb_class_name(CLASS_OF(self));
|
114
|
-
rb_raise(rb_eArgError, "put not supported for %s", StringValueCStr(name));
|
115
|
-
return self;
|
116
|
-
}
|
117
|
-
|
118
|
-
(*op->put)(memory, f->offset, value);
|
119
|
-
|
120
|
-
return self;
|
121
|
-
}
|
79
|
+
VALUE rbffi_StructInlineArrayClass = Qnil;
|
80
|
+
static ID id_pointer_ivar = 0, id_layout_ivar = 0;
|
81
|
+
static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0;
|
122
82
|
|
123
83
|
static inline char*
|
124
84
|
memory_address(VALUE self)
|
@@ -151,14 +111,14 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
151
111
|
|
152
112
|
/* Call up into ruby code to adjust the layout */
|
153
113
|
if (nargs > 1) {
|
154
|
-
s->rbLayout = rb_funcall2(CLASS_OF(self),
|
155
|
-
} else if (rb_cvar_defined(klass,
|
156
|
-
s->rbLayout = rb_cvar_get(klass,
|
114
|
+
s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
|
115
|
+
} else if (rb_cvar_defined(klass, id_layout_ivar)) {
|
116
|
+
s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
|
157
117
|
} else {
|
158
118
|
rb_raise(rb_eRuntimeError, "No Struct layout configured");
|
159
119
|
}
|
160
120
|
|
161
|
-
if (!rb_obj_is_kind_of(s->rbLayout,
|
121
|
+
if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
|
162
122
|
rb_raise(rb_eRuntimeError, "Invalid Struct layout");
|
163
123
|
}
|
164
124
|
|
@@ -196,53 +156,17 @@ struct_field(Struct* s, VALUE fieldName)
|
|
196
156
|
rb_raise(rb_eRuntimeError, "layout not set for Struct");
|
197
157
|
}
|
198
158
|
|
199
|
-
rbField = rb_hash_aref(layout->
|
159
|
+
rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
|
200
160
|
if (rbField == Qnil) {
|
201
|
-
VALUE str = rb_funcall2(fieldName,
|
161
|
+
VALUE str = rb_funcall2(fieldName, id_to_s, 0, NULL);
|
202
162
|
rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
|
203
163
|
}
|
204
164
|
|
205
165
|
return rbField;
|
206
166
|
}
|
207
167
|
|
208
|
-
static inline MemoryOp*
|
209
|
-
ptr_get_op(AbstractMemory* ptr, int type)
|
210
|
-
{
|
211
|
-
if (ptr == NULL || ptr->ops == NULL) {
|
212
|
-
return NULL;
|
213
|
-
}
|
214
|
-
switch (type) {
|
215
|
-
case NATIVE_INT8:
|
216
|
-
return ptr->ops->int8;
|
217
|
-
case NATIVE_UINT8:
|
218
|
-
return ptr->ops->uint8;
|
219
|
-
case NATIVE_INT16:
|
220
|
-
return ptr->ops->int16;
|
221
|
-
case NATIVE_UINT16:
|
222
|
-
return ptr->ops->uint16;
|
223
|
-
case NATIVE_INT32:
|
224
|
-
return ptr->ops->int32;
|
225
|
-
case NATIVE_UINT32:
|
226
|
-
return ptr->ops->uint32;
|
227
|
-
case NATIVE_INT64:
|
228
|
-
return ptr->ops->int64;
|
229
|
-
case NATIVE_UINT64:
|
230
|
-
return ptr->ops->uint64;
|
231
|
-
case NATIVE_FLOAT32:
|
232
|
-
return ptr->ops->float32;
|
233
|
-
case NATIVE_FLOAT64:
|
234
|
-
return ptr->ops->float64;
|
235
|
-
case NATIVE_POINTER:
|
236
|
-
return ptr->ops->pointer;
|
237
|
-
case NATIVE_STRING:
|
238
|
-
return ptr->ops->strptr;
|
239
|
-
default:
|
240
|
-
return NULL;
|
241
|
-
}
|
242
|
-
}
|
243
|
-
|
244
168
|
static VALUE
|
245
|
-
|
169
|
+
struct_aref(VALUE self, VALUE fieldName)
|
246
170
|
{
|
247
171
|
Struct* s;
|
248
172
|
VALUE rbField;
|
@@ -253,17 +177,17 @@ struct_get_field(VALUE self, VALUE fieldName)
|
|
253
177
|
rbField = struct_field(s, fieldName);
|
254
178
|
f = (StructField *) DATA_PTR(rbField);
|
255
179
|
|
256
|
-
op =
|
180
|
+
op = memory_get_op(s->pointer, f->type);
|
257
181
|
if (op != NULL) {
|
258
182
|
return (*op->get)(s->pointer, f->offset);
|
259
183
|
}
|
260
184
|
|
261
185
|
/* call up to the ruby code to fetch the value */
|
262
|
-
return rb_funcall2(rbField,
|
186
|
+
return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
|
263
187
|
}
|
264
188
|
|
265
189
|
static VALUE
|
266
|
-
|
190
|
+
struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
267
191
|
{
|
268
192
|
Struct* s;
|
269
193
|
VALUE rbField;
|
@@ -275,7 +199,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value)
|
|
275
199
|
rbField = struct_field(s, fieldName);
|
276
200
|
f = (StructField *) DATA_PTR(rbField);
|
277
201
|
|
278
|
-
op =
|
202
|
+
op = memory_get_op(s->pointer, f->type);
|
279
203
|
if (op != NULL) {
|
280
204
|
(*op->put)(s->pointer, f->offset, value);
|
281
205
|
return self;
|
@@ -284,7 +208,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value)
|
|
284
208
|
/* call up to the ruby code to set the value */
|
285
209
|
argv[0] = s->rbPointer;
|
286
210
|
argv[1] = value;
|
287
|
-
rb_funcall2(rbField,
|
211
|
+
rb_funcall2(rbField, id_put, 2, argv);
|
288
212
|
|
289
213
|
return self;
|
290
214
|
}
|
@@ -301,7 +225,7 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
301
225
|
Data_Get_Struct(self, Struct, s);
|
302
226
|
s->pointer = MEMORY(pointer);
|
303
227
|
s->rbPointer = pointer;
|
304
|
-
rb_ivar_set(self,
|
228
|
+
rb_ivar_set(self, id_pointer_ivar, pointer);
|
305
229
|
|
306
230
|
return self;
|
307
231
|
}
|
@@ -322,12 +246,12 @@ struct_set_layout(VALUE self, VALUE layout)
|
|
322
246
|
Struct* s;
|
323
247
|
Data_Get_Struct(self, Struct, s);
|
324
248
|
|
325
|
-
if (!rb_obj_is_kind_of(layout,
|
249
|
+
if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
|
326
250
|
rb_raise(rb_eArgError, "Invalid Struct layout");
|
327
251
|
}
|
328
252
|
|
329
253
|
Data_Get_Struct(layout, StructLayout, s->layout);
|
330
|
-
rb_ivar_set(self,
|
254
|
+
rb_ivar_set(self, id_layout_ivar, layout);
|
331
255
|
|
332
256
|
return self;
|
333
257
|
}
|
@@ -343,76 +267,451 @@ struct_get_layout(VALUE self)
|
|
343
267
|
}
|
344
268
|
|
345
269
|
static VALUE
|
346
|
-
|
270
|
+
struct_layout_builder_allocate(VALUE klass)
|
347
271
|
{
|
348
|
-
|
272
|
+
StructLayoutBuilder* builder;
|
349
273
|
VALUE obj;
|
350
|
-
|
351
|
-
obj = Data_Make_Struct(klass,
|
352
|
-
|
274
|
+
|
275
|
+
obj = Data_Make_Struct(klass, StructLayoutBuilder, struct_layout_builder_mark, struct_layout_builder_free, builder);
|
276
|
+
|
277
|
+
builder->size = 0;
|
278
|
+
builder->alignment = 1;
|
279
|
+
builder->isUnion = false;
|
280
|
+
builder->rbFieldNames = rb_ary_new();
|
281
|
+
builder->rbFieldMap = rb_hash_new();
|
353
282
|
|
354
283
|
return obj;
|
355
284
|
}
|
356
285
|
|
286
|
+
static void
|
287
|
+
struct_layout_builder_mark(StructLayoutBuilder* builder)
|
288
|
+
{
|
289
|
+
rb_gc_mark(builder->rbFieldNames);
|
290
|
+
rb_gc_mark(builder->rbFieldMap);
|
291
|
+
}
|
292
|
+
|
293
|
+
static void
|
294
|
+
struct_layout_builder_free(StructLayoutBuilder* builder)
|
295
|
+
{
|
296
|
+
xfree(builder);
|
297
|
+
}
|
298
|
+
|
357
299
|
static VALUE
|
358
|
-
|
300
|
+
struct_layout_builder_initialize(VALUE self)
|
359
301
|
{
|
360
|
-
|
361
|
-
|
302
|
+
StructLayoutBuilder* builder;
|
303
|
+
|
304
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
305
|
+
|
306
|
+
return self;
|
307
|
+
}
|
308
|
+
|
309
|
+
static VALUE
|
310
|
+
struct_layout_builder_get_size(VALUE self)
|
311
|
+
{
|
312
|
+
StructLayoutBuilder* builder;
|
313
|
+
|
314
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
315
|
+
|
316
|
+
return UINT2NUM(builder->size);
|
317
|
+
}
|
318
|
+
|
319
|
+
static VALUE
|
320
|
+
struct_layout_builder_set_size(VALUE self, VALUE rbSize)
|
321
|
+
{
|
322
|
+
StructLayoutBuilder* builder;
|
323
|
+
unsigned int size = NUM2UINT(rbSize);
|
324
|
+
|
325
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
326
|
+
builder->size = MAX(size, builder->size);
|
327
|
+
|
328
|
+
return UINT2NUM(builder->size);
|
329
|
+
}
|
330
|
+
|
331
|
+
static VALUE
|
332
|
+
struct_layout_builder_get_alignment(VALUE self)
|
333
|
+
{
|
334
|
+
StructLayoutBuilder* builder;
|
335
|
+
|
336
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
337
|
+
|
338
|
+
return UINT2NUM(builder->alignment);
|
339
|
+
}
|
340
|
+
|
341
|
+
static VALUE
|
342
|
+
struct_layout_builder_set_alignment(VALUE self, VALUE rbAlign)
|
343
|
+
{
|
344
|
+
StructLayoutBuilder* builder;
|
345
|
+
unsigned int align = NUM2UINT(rbAlign);
|
346
|
+
|
347
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
348
|
+
builder->size = MAX(align, builder->alignment);
|
349
|
+
|
350
|
+
return UINT2NUM(builder->alignment);
|
351
|
+
}
|
362
352
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
353
|
+
static VALUE
|
354
|
+
struct_layout_builder_set_union(VALUE self, VALUE rbUnion)
|
355
|
+
{
|
356
|
+
StructLayoutBuilder* builder;
|
357
|
+
|
358
|
+
|
359
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
360
|
+
builder->isUnion = RTEST(rbUnion);
|
361
|
+
|
362
|
+
return rbUnion;
|
363
|
+
}
|
364
|
+
|
365
|
+
static VALUE
|
366
|
+
struct_layout_builder_union_p(VALUE self)
|
367
|
+
{
|
368
|
+
StructLayoutBuilder* builder;
|
369
|
+
|
370
|
+
|
371
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
372
|
+
|
373
|
+
|
374
|
+
return builder->isUnion ? Qtrue : Qfalse;
|
375
|
+
}
|
376
|
+
|
377
|
+
static void
|
378
|
+
store_field(StructLayoutBuilder* builder, VALUE rbName, VALUE rbField,
|
379
|
+
unsigned int offset, unsigned int size, unsigned int alignment)
|
380
|
+
{
|
381
|
+
rb_ary_push(builder->rbFieldNames, rbName);
|
382
|
+
rb_hash_aset(builder->rbFieldMap, rbName, rbField);
|
383
|
+
|
384
|
+
builder->alignment = MAX(builder->alignment, alignment);
|
385
|
+
|
386
|
+
if (builder->isUnion) {
|
387
|
+
builder->size = MAX(builder->size, size);
|
388
|
+
} else {
|
389
|
+
builder->size = MAX(builder->size, offset + size);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
static int
|
394
|
+
calculate_offset(StructLayoutBuilder* builder, int alignment, VALUE rbOffset)
|
395
|
+
{
|
396
|
+
if (rbOffset != Qnil) {
|
397
|
+
return NUM2UINT(rbOffset);
|
398
|
+
} else {
|
399
|
+
return builder->isUnion ? 0 : align(builder->size, alignment);
|
400
|
+
}
|
401
|
+
}
|
402
|
+
|
403
|
+
static VALUE
|
404
|
+
struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
|
405
|
+
{
|
406
|
+
StructLayoutBuilder* builder;
|
407
|
+
VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
|
408
|
+
unsigned int size, alignment, offset;
|
409
|
+
int nargs;
|
410
|
+
|
411
|
+
nargs = rb_scan_args(argc, argv, "21", &rbName, &rbType, &rbOffset);
|
367
412
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
413
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
414
|
+
|
415
|
+
alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
|
416
|
+
size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
|
417
|
+
|
418
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
419
|
+
|
420
|
+
//
|
421
|
+
// If a primitive type was passed in as the type arg, try and convert
|
422
|
+
//
|
423
|
+
if (!rb_obj_is_kind_of(rbType, rbffi_StructLayoutFieldClass)) {
|
424
|
+
VALUE fargv[3], rbFieldClass;
|
425
|
+
fargv[0] = rbName;
|
426
|
+
fargv[1] = UINT2NUM(offset);
|
427
|
+
fargv[2] = rbType;
|
428
|
+
if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
|
429
|
+
rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
|
430
|
+
} else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
|
431
|
+
rbFieldClass = rbffi_StructLayoutStructFieldClass;
|
432
|
+
} else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
|
433
|
+
rbFieldClass = rbffi_StructLayoutArrayFieldClass;
|
434
|
+
} else {
|
435
|
+
rbFieldClass = rbffi_StructLayoutFieldClass;
|
378
436
|
}
|
379
|
-
|
437
|
+
|
438
|
+
rbField = rb_class_new_instance(3, fargv, rbFieldClass);
|
439
|
+
} else {
|
440
|
+
rbField = rbType;
|
441
|
+
}
|
442
|
+
|
443
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
444
|
+
|
445
|
+
return self;
|
446
|
+
}
|
447
|
+
|
448
|
+
static VALUE
|
449
|
+
struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
|
450
|
+
{
|
451
|
+
StructLayoutBuilder* builder;
|
452
|
+
VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil, rbStructClass = Qnil;
|
453
|
+
VALUE fargv[3];
|
454
|
+
unsigned int size, alignment, offset;
|
455
|
+
int nargs;
|
456
|
+
|
457
|
+
nargs = rb_scan_args(argc, argv, "21", &rbName, &rbStructClass, &rbOffset);
|
458
|
+
|
459
|
+
if (!rb_obj_is_instance_of(rbStructClass, rb_cClass) || !rb_class_inherited(rbStructClass, rbffi_StructClass)) {
|
460
|
+
rb_raise(rb_eTypeError, "wrong argument type. Expected subclass of FFI::Struct");
|
380
461
|
}
|
462
|
+
|
463
|
+
rbType = rb_class_new_instance(1, &rbStructClass, rbffi_StructByValueClass);
|
464
|
+
|
465
|
+
alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
|
466
|
+
size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
|
467
|
+
|
468
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
469
|
+
|
470
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
471
|
+
|
472
|
+
fargv[0] = rbName;
|
473
|
+
fargv[1] = UINT2NUM(offset);
|
474
|
+
fargv[2] = rbType;
|
475
|
+
rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutStructFieldClass);
|
476
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
477
|
+
|
381
478
|
return self;
|
382
479
|
}
|
383
480
|
|
384
481
|
static VALUE
|
385
|
-
|
482
|
+
struct_layout_builder_add_array(int argc, VALUE* argv, VALUE self)
|
386
483
|
{
|
387
|
-
|
484
|
+
StructLayoutBuilder* builder;
|
485
|
+
VALUE rbName = Qnil, rbType = Qnil, rbLength = Qnil, rbOffset = Qnil, rbField;
|
486
|
+
VALUE fargv[3], aargv[2];
|
487
|
+
unsigned int size, alignment, offset;
|
488
|
+
int nargs;
|
489
|
+
|
490
|
+
nargs = rb_scan_args(argc, argv, "31", &rbName, &rbType, &rbLength, &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)) * NUM2UINT(rbLength);
|
388
496
|
|
389
|
-
|
497
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
390
498
|
|
391
|
-
|
499
|
+
aargv[0] = rbType;
|
500
|
+
aargv[1] = rbLength;
|
501
|
+
fargv[0] = rbName;
|
502
|
+
fargv[1] = UINT2NUM(offset);
|
503
|
+
fargv[2] = rb_class_new_instance(2, aargv, rbffi_ArrayTypeClass);
|
504
|
+
rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutArrayFieldClass);
|
505
|
+
|
506
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
507
|
+
|
508
|
+
return self;
|
509
|
+
}
|
510
|
+
|
511
|
+
static inline int
|
512
|
+
align(int offset, int align)
|
513
|
+
{
|
514
|
+
return align + ((offset - 1) & ~(align - 1));
|
392
515
|
}
|
393
516
|
|
517
|
+
static VALUE
|
518
|
+
struct_layout_builder_build(VALUE self)
|
519
|
+
{
|
520
|
+
StructLayoutBuilder* builder;
|
521
|
+
VALUE argv[4];
|
522
|
+
|
523
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
524
|
+
|
525
|
+
argv[0] = builder->rbFieldNames;
|
526
|
+
argv[1] = builder->rbFieldMap;
|
527
|
+
argv[2] = UINT2NUM(align(builder->size, builder->alignment)); // tail padding
|
528
|
+
argv[3] = UINT2NUM(builder->alignment);
|
529
|
+
|
530
|
+
return rb_class_new_instance(4, argv, rbffi_StructLayoutClass);
|
531
|
+
}
|
532
|
+
|
533
|
+
static VALUE
|
534
|
+
inline_array_allocate(VALUE klass)
|
535
|
+
{
|
536
|
+
InlineArray* array;
|
537
|
+
VALUE obj;
|
538
|
+
|
539
|
+
obj = Data_Make_Struct(klass, InlineArray, inline_array_mark, -1, array);
|
540
|
+
array->rbField = Qnil;
|
541
|
+
array->rbMemory = Qnil;
|
542
|
+
|
543
|
+
return obj;
|
544
|
+
}
|
394
545
|
|
395
546
|
static void
|
396
|
-
|
547
|
+
inline_array_mark(InlineArray* array)
|
548
|
+
{
|
549
|
+
rb_gc_mark(array->rbField);
|
550
|
+
rb_gc_mark(array->rbMemory);
|
551
|
+
}
|
552
|
+
|
553
|
+
static VALUE
|
554
|
+
inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
555
|
+
{
|
556
|
+
InlineArray* array;
|
557
|
+
ArrayType* arrayType;
|
558
|
+
|
559
|
+
Data_Get_Struct(self, InlineArray, array);
|
560
|
+
array->rbMemory = rbMemory;
|
561
|
+
array->rbField = rbField;
|
562
|
+
|
563
|
+
Data_Get_Struct(rbMemory, AbstractMemory, array->memory);
|
564
|
+
Data_Get_Struct(rbField, StructField, array->field);
|
565
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
566
|
+
Data_Get_Struct(arrayType->rbComponentType, Type, array->componentType);
|
567
|
+
|
568
|
+
array->op = memory_get_op(array->memory, array->componentType);
|
569
|
+
if (array->op == NULL) {
|
570
|
+
rb_raise(rb_eRuntimeError, "invalid memory ops");
|
571
|
+
}
|
572
|
+
|
573
|
+
return self;
|
574
|
+
}
|
575
|
+
|
576
|
+
static VALUE
|
577
|
+
inline_array_size(VALUE self)
|
578
|
+
{
|
579
|
+
InlineArray* array;
|
580
|
+
|
581
|
+
Data_Get_Struct(self, InlineArray, array);
|
582
|
+
|
583
|
+
return UINT2NUM(array->field->type->ffiType->size);
|
584
|
+
}
|
585
|
+
|
586
|
+
static int
|
587
|
+
inline_array_offset(InlineArray* array, unsigned int index)
|
397
588
|
{
|
398
|
-
|
589
|
+
return array->field->offset + (index * array->componentType->ffiType->size);
|
399
590
|
}
|
400
591
|
|
592
|
+
static VALUE
|
593
|
+
inline_array_aref(VALUE self, VALUE rbIndex)
|
594
|
+
{
|
595
|
+
InlineArray* array;
|
596
|
+
|
597
|
+
Data_Get_Struct(self, InlineArray, array);
|
598
|
+
|
599
|
+
return array->op->get(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)));
|
600
|
+
}
|
601
|
+
|
602
|
+
static VALUE
|
603
|
+
inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
|
604
|
+
{
|
605
|
+
InlineArray* array;
|
606
|
+
|
607
|
+
Data_Get_Struct(self, InlineArray, array);
|
608
|
+
|
609
|
+
array->op->put(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)),
|
610
|
+
rbValue);
|
611
|
+
|
612
|
+
return rbValue;
|
613
|
+
}
|
614
|
+
|
615
|
+
static VALUE
|
616
|
+
inline_array_each(VALUE self)
|
617
|
+
{
|
618
|
+
InlineArray* array;
|
619
|
+
ArrayType* arrayType;
|
620
|
+
|
621
|
+
int i;
|
622
|
+
|
623
|
+
Data_Get_Struct(self, InlineArray, array);
|
624
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
625
|
+
|
626
|
+
for (i = 0; i < arrayType->length; ++i) {
|
627
|
+
int offset = inline_array_offset(array, i);
|
628
|
+
rb_yield(array->op->get(array->memory, offset));
|
629
|
+
}
|
630
|
+
|
631
|
+
return self;
|
632
|
+
}
|
633
|
+
|
634
|
+
static VALUE
|
635
|
+
inline_array_to_a(VALUE self)
|
636
|
+
{
|
637
|
+
InlineArray* array;
|
638
|
+
ArrayType* arrayType;
|
639
|
+
VALUE obj;
|
640
|
+
int i;
|
641
|
+
|
642
|
+
Data_Get_Struct(self, InlineArray, array);
|
643
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
644
|
+
obj = rb_ary_new2(arrayType->length);
|
645
|
+
|
646
|
+
|
647
|
+
for (i = 0; i < arrayType->length; ++i) {
|
648
|
+
int offset = inline_array_offset(array, i);
|
649
|
+
rb_ary_push(obj, array->op->get(array->memory, offset));
|
650
|
+
}
|
651
|
+
|
652
|
+
return obj;
|
653
|
+
}
|
654
|
+
|
655
|
+
static VALUE
|
656
|
+
inline_array_to_s(VALUE self)
|
657
|
+
{
|
658
|
+
InlineArray* array;
|
659
|
+
ArrayType* arrayType;
|
660
|
+
VALUE argv[2];
|
661
|
+
|
662
|
+
Data_Get_Struct(self, InlineArray, array);
|
663
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
664
|
+
|
665
|
+
if (arrayType->componentType->nativeType != NATIVE_INT8 && arrayType->componentType->nativeType != NATIVE_UINT8) {
|
666
|
+
rb_raise(rb_eNoMethodError, "to_s not defined for this array type");
|
667
|
+
return Qnil;
|
668
|
+
}
|
669
|
+
|
670
|
+
argv[0] = UINT2NUM(array->field->offset);
|
671
|
+
argv[1] = UINT2NUM(arrayType->length);
|
672
|
+
|
673
|
+
return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
|
674
|
+
}
|
675
|
+
|
676
|
+
|
677
|
+
static VALUE
|
678
|
+
inline_array_to_ptr(VALUE self)
|
679
|
+
{
|
680
|
+
InlineArray* array;
|
681
|
+
AbstractMemory* ptr;
|
682
|
+
VALUE rbOffset, rbPointer;
|
683
|
+
|
684
|
+
Data_Get_Struct(self, InlineArray, array);
|
685
|
+
|
686
|
+
rbOffset = UINT2NUM(array->field->offset);
|
687
|
+
rbPointer = rb_funcall2(array->rbMemory, rb_intern("+"), 1, &rbOffset);
|
688
|
+
Data_Get_Struct(rbPointer, AbstractMemory, ptr);
|
689
|
+
|
690
|
+
// Restrict the size of the pointer so ops like ptr.get_string(0) are bounds checked
|
691
|
+
ptr->size = MIN(ptr->size, array->field->type->ffiType->size);
|
692
|
+
|
693
|
+
return rbPointer;
|
694
|
+
}
|
695
|
+
|
696
|
+
|
401
697
|
void
|
402
698
|
rbffi_Struct_Init(VALUE moduleFFI)
|
403
699
|
{
|
404
|
-
VALUE
|
700
|
+
VALUE StructClass;
|
701
|
+
|
702
|
+
rbffi_StructLayout_Init(moduleFFI);
|
703
|
+
|
405
704
|
rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
|
406
705
|
rb_global_variable(&rbffi_StructClass);
|
407
706
|
|
408
|
-
StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rb_cObject);
|
409
|
-
rb_global_variable(&StructLayoutClass);
|
410
707
|
|
411
708
|
StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
|
412
709
|
rb_global_variable(&StructLayoutBuilderClass);
|
413
710
|
|
414
|
-
|
415
|
-
rb_global_variable(&
|
711
|
+
rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
|
712
|
+
rb_global_variable(&rbffi_StructInlineArrayClass);
|
713
|
+
|
714
|
+
|
416
715
|
|
417
716
|
rb_define_alloc_func(StructClass, struct_allocate);
|
418
717
|
rb_define_method(StructClass, "initialize", struct_initialize, -1);
|
@@ -430,48 +729,42 @@ rbffi_Struct_Init(VALUE moduleFFI)
|
|
430
729
|
rb_define_method(StructClass, "layout", struct_get_layout, 0);
|
431
730
|
rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
|
432
731
|
|
433
|
-
rb_define_method(StructClass, "[]",
|
434
|
-
rb_define_method(StructClass, "[]=",
|
732
|
+
rb_define_method(StructClass, "[]", struct_aref, 1);
|
733
|
+
rb_define_method(StructClass, "[]=", struct_aset, 2);
|
435
734
|
|
436
|
-
rb_define_alloc_func(StructFieldClass, struct_field_allocate);
|
437
|
-
rb_define_method(StructFieldClass, "initialize", struct_field_initialize, -1);
|
438
|
-
rb_define_method(StructFieldClass, "offset", struct_field_offset, 0);
|
439
|
-
rb_define_method(StructFieldClass, "put", struct_field_put, 2);
|
440
|
-
rb_define_method(StructFieldClass, "get", struct_field_get, 1);
|
441
|
-
|
442
|
-
rb_define_alloc_func(StructLayoutClass, struct_layout_allocate);
|
443
|
-
rb_define_method(StructLayoutClass, "initialize", struct_layout_initialize, 4);
|
444
|
-
rb_define_method(StructLayoutClass, "[]", struct_layout_aref, 1);
|
445
|
-
|
446
|
-
pointer_var_id = rb_intern("@pointer");
|
447
|
-
layout_var_id = rb_intern("@layout");
|
448
|
-
layout_id = rb_intern("layout");
|
449
|
-
get_id = rb_intern("get");
|
450
|
-
put_id = rb_intern("put");
|
451
|
-
to_ptr = rb_intern("to_ptr");
|
452
|
-
to_s = rb_intern("to_s");
|
453
|
-
SIZE_ID = rb_intern("SIZE");
|
454
|
-
ALIGN_ID = rb_intern("ALIGN");
|
455
|
-
TYPE_ID = rb_intern("TYPE");
|
456
|
-
#undef FIELD
|
457
|
-
#define FIELD(name, typeName, nativeType, T) do { \
|
458
|
-
typedef struct { char c; T v; } s; \
|
459
|
-
klass = rb_define_class_under(StructLayoutBuilderClass, #name, StructFieldClass); \
|
460
|
-
rb_define_const(klass, "ALIGN", INT2NUM((sizeof(s) - sizeof(T)))); \
|
461
|
-
rb_define_const(klass, "SIZE", INT2NUM(sizeof(T))); \
|
462
|
-
rb_define_const(klass, "TYPE", INT2NUM(nativeType)); \
|
463
|
-
} while(0)
|
464
735
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
736
|
+
|
737
|
+
rb_define_alloc_func(StructLayoutBuilderClass, struct_layout_builder_allocate);
|
738
|
+
rb_define_method(StructLayoutBuilderClass, "initialize", struct_layout_builder_initialize, 0);
|
739
|
+
rb_define_method(StructLayoutBuilderClass, "build", struct_layout_builder_build, 0);
|
740
|
+
|
741
|
+
rb_define_method(StructLayoutBuilderClass, "alignment", struct_layout_builder_get_alignment, 0);
|
742
|
+
rb_define_method(StructLayoutBuilderClass, "alignment=", struct_layout_builder_set_alignment, 1);
|
743
|
+
rb_define_method(StructLayoutBuilderClass, "size", struct_layout_builder_get_size, 0);
|
744
|
+
rb_define_method(StructLayoutBuilderClass, "size=", struct_layout_builder_set_size, 1);
|
745
|
+
rb_define_method(StructLayoutBuilderClass, "union=", struct_layout_builder_set_union, 1);
|
746
|
+
rb_define_method(StructLayoutBuilderClass, "union?", struct_layout_builder_union_p, 0);
|
747
|
+
rb_define_method(StructLayoutBuilderClass, "add_field", struct_layout_builder_add_field, -1);
|
748
|
+
rb_define_method(StructLayoutBuilderClass, "add_array", struct_layout_builder_add_array, -1);
|
749
|
+
rb_define_method(StructLayoutBuilderClass, "add_struct", struct_layout_builder_add_struct, -1);
|
750
|
+
|
751
|
+
rb_include_module(rbffi_StructInlineArrayClass, rb_mEnumerable);
|
752
|
+
rb_define_alloc_func(rbffi_StructInlineArrayClass, inline_array_allocate);
|
753
|
+
rb_define_method(rbffi_StructInlineArrayClass, "initialize", inline_array_initialize, 2);
|
754
|
+
rb_define_method(rbffi_StructInlineArrayClass, "[]", inline_array_aref, 1);
|
755
|
+
rb_define_method(rbffi_StructInlineArrayClass, "[]=", inline_array_aset, 2);
|
756
|
+
rb_define_method(rbffi_StructInlineArrayClass, "each", inline_array_each, 0);
|
757
|
+
rb_define_method(rbffi_StructInlineArrayClass, "size", inline_array_size, 0);
|
758
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_a", inline_array_to_a, 0);
|
759
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_s", inline_array_to_s, 0);
|
760
|
+
rb_define_alias(rbffi_StructInlineArrayClass, "to_str", "to_s");
|
761
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_ptr", inline_array_to_ptr, 0);
|
762
|
+
|
763
|
+
id_pointer_ivar = rb_intern("@pointer");
|
764
|
+
id_layout_ivar = rb_intern("@layout");
|
765
|
+
id_layout = rb_intern("layout");
|
766
|
+
id_get = rb_intern("get");
|
767
|
+
id_put = rb_intern("put");
|
768
|
+
id_to_ptr = rb_intern("to_ptr");
|
769
|
+
id_to_s = rb_intern("to_s");
|
477
770
|
}
|