ffi 0.3.0 → 0.4.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/README.rdoc +51 -1
- data/Rakefile +47 -28
- data/ext/ffi_c/AbstractMemory.c +149 -65
- data/ext/ffi_c/AbstractMemory.h +34 -4
- data/ext/ffi_c/AutoPointer.c +15 -18
- data/ext/ffi_c/AutoPointer.h +2 -2
- data/ext/ffi_c/Buffer.c +79 -44
- data/ext/ffi_c/Callback.c +133 -62
- data/ext/ffi_c/Callback.h +11 -5
- data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +88 -24
- data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
- data/ext/ffi_c/Invoker.c +154 -190
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +30 -20
- data/ext/ffi_c/MemoryPointer.h +3 -3
- data/ext/ffi_c/NullPointer.c +67 -28
- data/ext/ffi_c/Platform.c +9 -10
- data/ext/ffi_c/Platform.h +1 -1
- data/ext/ffi_c/Pointer.c +67 -30
- data/ext/ffi_c/Pointer.h +8 -6
- data/ext/ffi_c/Struct.c +202 -267
- data/ext/ffi_c/Struct.h +2 -2
- data/ext/ffi_c/Type.c +230 -0
- data/ext/ffi_c/Type.h +28 -0
- data/ext/ffi_c/Types.c +48 -6
- data/ext/ffi_c/Types.h +8 -2
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +6 -5
- data/ext/ffi_c/ffi.c +21 -44
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +30 -10
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +4 -2
- data/ext/ffi_c/rbffi.h +6 -8
- data/gen/Rakefile +12 -0
- data/lib/ffi/autopointer.rb +1 -1
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/ffi.rb +5 -6
- data/lib/ffi/io.rb +15 -1
- data/lib/ffi/library.rb +79 -18
- data/lib/ffi/pointer.rb +2 -2
- data/lib/ffi/struct.rb +68 -14
- data/lib/ffi/types.rb +6 -3
- data/lib/ffi/variadic.rb +2 -2
- data/lib/ffi.rb +10 -1
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/callback_spec.rb +217 -17
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/managed_struct_spec.rb +6 -1
- data/spec/ffi/number_spec.rb +30 -0
- data/spec/ffi/pointer_spec.rb +33 -8
- data/spec/ffi/rbx/memory_pointer_spec.rb +0 -6
- data/spec/ffi/spec_helper.rb +5 -1
- data/spec/ffi/string_spec.rb +65 -4
- data/spec/ffi/struct_callback_spec.rb +41 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +44 -21
- metadata +31 -69
- data/ext/ffi_c/ffi.mk +0 -23
- data/nbproject/Makefile-Default.mk +0 -57
- data/nbproject/Makefile-impl.mk +0 -123
- data/nbproject/Package-Default.bash +0 -72
- data/nbproject/configurations.xml +0 -293
- data/nbproject/private/configurations.xml +0 -22
- data/nbproject/private/private.xml +0 -7
- data/nbproject/project.properties +0 -0
- data/nbproject/project.xml +0 -15
- data/samples/getlogin.rb +0 -7
- data/samples/getpid.rb +0 -7
- data/samples/gettimeofday.rb +0 -17
- data/samples/hello.rb +0 -6
- data/samples/inotify.rb +0 -59
- data/samples/pty.rb +0 -75
- data/samples/qsort.rb +0 -20
- data/samples/sample_helper.rb +0 -6
data/ext/ffi_c/Struct.c
CHANGED
|
@@ -29,30 +29,21 @@ typedef struct StructLayoutBuilder {
|
|
|
29
29
|
unsigned int offset;
|
|
30
30
|
} StructLayoutBuilder;
|
|
31
31
|
|
|
32
|
-
static void struct_field_mark(StructField *);
|
|
33
|
-
static void struct_field_free(StructField *);
|
|
34
32
|
static void struct_mark(Struct *);
|
|
35
|
-
static void struct_free(Struct *);
|
|
36
33
|
static void struct_layout_mark(StructLayout *);
|
|
37
|
-
static
|
|
34
|
+
static inline MemoryOp* ptr_get_op(AbstractMemory* ptr, int type);
|
|
38
35
|
|
|
39
|
-
VALUE
|
|
40
|
-
static VALUE
|
|
41
|
-
static VALUE
|
|
42
|
-
static ID
|
|
43
|
-
static ID
|
|
44
|
-
|
|
45
|
-
#define FIELD_CAST(obj) ((StructField *)((TYPE(obj) == T_DATA && rb_obj_is_kind_of(obj, classStructField)) \
|
|
46
|
-
? DATA_PTR(obj) : (rb_raise(rb_eArgError, "StructField expected"), NULL)))
|
|
47
|
-
|
|
48
|
-
#define LAYOUT_CAST(obj) ((StructLayout *)((TYPE(obj) == T_DATA && rb_obj_is_kind_of(obj, classStructLayout)) \
|
|
49
|
-
? DATA_PTR(obj) : (rb_raise(rb_eArgError, "StructLayout expected"), NULL)))
|
|
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;
|
|
50
41
|
|
|
51
42
|
static VALUE
|
|
52
43
|
struct_field_allocate(VALUE klass)
|
|
53
44
|
{
|
|
54
45
|
StructField* field;
|
|
55
|
-
return Data_Make_Struct(klass, StructField,
|
|
46
|
+
return Data_Make_Struct(klass, StructField, NULL, -1, field);
|
|
56
47
|
}
|
|
57
48
|
|
|
58
49
|
static VALUE
|
|
@@ -67,17 +58,19 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
67
58
|
nargs = rb_scan_args(argc, argv, "11", &offset, &info);
|
|
68
59
|
|
|
69
60
|
field->offset = NUM2UINT(offset);
|
|
70
|
-
if (rb_const_defined(CLASS_OF(self),
|
|
71
|
-
field->type = NUM2UINT(rb_const_get(CLASS_OF(self),
|
|
61
|
+
if (rb_const_defined(CLASS_OF(self), TYPE_ID)) {
|
|
62
|
+
field->type = NUM2UINT(rb_const_get(CLASS_OF(self), TYPE_ID));
|
|
72
63
|
} else {
|
|
73
64
|
field->type = ~0;
|
|
74
65
|
}
|
|
66
|
+
|
|
75
67
|
#ifdef notyet
|
|
76
|
-
field->size = NUM2UINT(rb_const_get(klass,
|
|
77
|
-
field->align = NUM2UINT(rb_const_get(klass,
|
|
68
|
+
field->size = NUM2UINT(rb_const_get(klass, SIZE_ID));
|
|
69
|
+
field->align = NUM2UINT(rb_const_get(klass, ALIGN_ID));
|
|
78
70
|
#endif
|
|
79
71
|
rb_iv_set(self, "@off", offset);
|
|
80
72
|
rb_iv_set(self, "@info", info);
|
|
73
|
+
|
|
81
74
|
return self;
|
|
82
75
|
}
|
|
83
76
|
|
|
@@ -89,135 +82,67 @@ struct_field_offset(VALUE self)
|
|
|
89
82
|
return UINT2NUM(field->offset);
|
|
90
83
|
}
|
|
91
84
|
|
|
92
|
-
static
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
}
|
|
96
|
-
static void
|
|
97
|
-
struct_field_free(StructField *f)
|
|
85
|
+
static VALUE
|
|
86
|
+
struct_field_get(VALUE self, VALUE pointer)
|
|
98
87
|
{
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
StructField* f;
|
|
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;
|
|
101
98
|
}
|
|
102
|
-
}
|
|
103
99
|
|
|
104
|
-
|
|
105
|
-
memory_address(VALUE self)
|
|
106
|
-
{
|
|
107
|
-
return ((AbstractMemory *)DATA_PTR((self)))->address;
|
|
100
|
+
return (*op->get)(memory, f->offset);
|
|
108
101
|
}
|
|
109
102
|
|
|
110
|
-
static
|
|
111
|
-
|
|
103
|
+
static VALUE
|
|
104
|
+
struct_field_put(VALUE self, VALUE pointer, VALUE value)
|
|
112
105
|
{
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return
|
|
123
|
-
} else if (rb_respond_to(value, to_ptr)) {
|
|
124
|
-
VALUE ptr = rb_funcall2(value, to_ptr, 0, NULL);
|
|
125
|
-
if (rb_obj_is_kind_of(ptr, rb_FFI_Pointer_class) && TYPE(ptr) == T_DATA) {
|
|
126
|
-
return memory_address(ptr);
|
|
127
|
-
} else {
|
|
128
|
-
rb_raise(rb_eArgError, "to_ptr returned an invalid pointer");
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
rb_raise(rb_eArgError, "value is not a pointer");
|
|
106
|
+
StructField* f;
|
|
107
|
+
MemoryOp* op;
|
|
108
|
+
AbstractMemory* memory = MEMORY(pointer);
|
|
109
|
+
|
|
110
|
+
Data_Get_Struct(self, StructField, f);
|
|
111
|
+
op = ptr_get_op(memory, f->type);
|
|
112
|
+
if (op == NULL) {
|
|
113
|
+
VALUE name = rb_class_name(CLASS_OF(self));
|
|
114
|
+
rb_raise(rb_eArgError, "put not supported for %s", StringValueCStr(name));
|
|
115
|
+
return self;
|
|
132
116
|
}
|
|
133
|
-
|
|
117
|
+
|
|
118
|
+
(*op->put)(memory, f->offset, value);
|
|
134
119
|
|
|
135
|
-
|
|
136
|
-
pointer_new(char* value)
|
|
137
|
-
{
|
|
138
|
-
return rb_FFI_Pointer_new(value);
|
|
120
|
+
return self;
|
|
139
121
|
}
|
|
140
122
|
|
|
141
123
|
static inline char*
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
rb_raise(rb_eArgError, "Cannot set :string fields");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
static inline VALUE
|
|
148
|
-
string_from_native(char* value)
|
|
124
|
+
memory_address(VALUE self)
|
|
149
125
|
{
|
|
150
|
-
return
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
#define FIELD_OP(name, type, toNative, fromNative) \
|
|
154
|
-
static VALUE struct_field_put_##name(VALUE self, VALUE pointer, VALUE value); \
|
|
155
|
-
static inline void ptr_put_##name(AbstractMemory* ptr, StructField* field, VALUE value); \
|
|
156
|
-
static inline VALUE ptr_get_##name(AbstractMemory* ptr, StructField* field); \
|
|
157
|
-
static inline void \
|
|
158
|
-
ptr_put_##name(AbstractMemory* ptr, StructField* field, VALUE value) \
|
|
159
|
-
{ \
|
|
160
|
-
type tmp = toNative(value); \
|
|
161
|
-
memcpy(ptr->address + field->offset, &tmp, sizeof(tmp)); \
|
|
162
|
-
} \
|
|
163
|
-
static inline VALUE \
|
|
164
|
-
ptr_get_##name(AbstractMemory* ptr, StructField* field) \
|
|
165
|
-
{ \
|
|
166
|
-
type tmp; \
|
|
167
|
-
memcpy(&tmp, ptr->address + field->offset, sizeof(tmp)); \
|
|
168
|
-
return fromNative(tmp); \
|
|
169
|
-
} \
|
|
170
|
-
static VALUE \
|
|
171
|
-
struct_field_put_##name(VALUE self, VALUE pointer, VALUE value) \
|
|
172
|
-
{ \
|
|
173
|
-
StructField* f; Data_Get_Struct(self, StructField, f); \
|
|
174
|
-
ptr_put_##name(MEMORY(pointer), f, value); \
|
|
175
|
-
return self; \
|
|
176
|
-
} \
|
|
177
|
-
static VALUE struct_field_get_##name(VALUE self, VALUE pointer); \
|
|
178
|
-
static VALUE \
|
|
179
|
-
struct_field_get_##name(VALUE self, VALUE pointer) \
|
|
180
|
-
{ \
|
|
181
|
-
StructField* f; Data_Get_Struct(self, StructField, f); \
|
|
182
|
-
return ptr_get_##name(MEMORY(pointer), f); \
|
|
126
|
+
return ((AbstractMemory *)DATA_PTR((self)))->address;
|
|
183
127
|
}
|
|
184
128
|
|
|
185
|
-
FIELD_OP(int8, int8_t, NUM2INT, INT2NUM);
|
|
186
|
-
FIELD_OP(uint8, uint8_t, NUM2UINT, UINT2NUM);
|
|
187
|
-
FIELD_OP(int16, int16_t, NUM2INT, INT2NUM);
|
|
188
|
-
FIELD_OP(uint16, uint16_t, NUM2UINT, UINT2NUM);
|
|
189
|
-
FIELD_OP(int32, int32_t, NUM2INT, INT2NUM);
|
|
190
|
-
FIELD_OP(uint32, uint32_t, NUM2UINT, UINT2NUM);
|
|
191
|
-
FIELD_OP(int64, int64_t, NUM2LL, LL2NUM);
|
|
192
|
-
FIELD_OP(uint64, uint64_t, NUM2ULL, ULL2NUM);
|
|
193
|
-
FIELD_OP(float32, float, NUM2DBL, rb_float_new);
|
|
194
|
-
FIELD_OP(float64, double, NUM2DBL, rb_float_new);
|
|
195
|
-
FIELD_OP(pointer, char*, pointer_native, pointer_new);
|
|
196
|
-
FIELD_OP(string, char*, string_to_native, string_from_native);
|
|
197
|
-
|
|
198
129
|
static VALUE
|
|
199
130
|
struct_allocate(VALUE klass)
|
|
200
131
|
{
|
|
201
132
|
Struct* s;
|
|
202
|
-
VALUE
|
|
133
|
+
VALUE obj = Data_Make_Struct(klass, Struct, struct_mark, -1, s);
|
|
203
134
|
|
|
204
135
|
s->rbPointer = Qnil;
|
|
205
|
-
s->pointer = NULL;
|
|
206
136
|
s->rbLayout = Qnil;
|
|
207
|
-
s->layout = NULL;
|
|
208
137
|
|
|
209
|
-
|
|
210
|
-
s->rbLayout = rb_cvar_get(klass, layoutID);
|
|
211
|
-
Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
|
|
212
|
-
}
|
|
213
|
-
return retval;
|
|
138
|
+
return obj;
|
|
214
139
|
}
|
|
215
140
|
|
|
216
141
|
static VALUE
|
|
217
142
|
struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
218
143
|
{
|
|
219
144
|
Struct* s;
|
|
220
|
-
VALUE rbPointer = Qnil, rest = Qnil;
|
|
145
|
+
VALUE rbPointer = Qnil, rest = Qnil, klass = CLASS_OF(self);
|
|
221
146
|
int nargs;
|
|
222
147
|
|
|
223
148
|
Data_Get_Struct(self, Struct, s);
|
|
@@ -226,38 +151,40 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
226
151
|
|
|
227
152
|
/* Call up into ruby code to adjust the layout */
|
|
228
153
|
if (nargs > 1) {
|
|
229
|
-
s->rbLayout = rb_funcall2(CLASS_OF(self),
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
154
|
+
s->rbLayout = rb_funcall2(CLASS_OF(self), layout_id, RARRAY_LEN(rest), RARRAY_PTR(rest));
|
|
155
|
+
} else if (rb_cvar_defined(klass, layout_var_id)) {
|
|
156
|
+
s->rbLayout = rb_cvar_get(klass, layout_var_id);
|
|
157
|
+
} else {
|
|
158
|
+
rb_raise(rb_eRuntimeError, "No Struct layout configured");
|
|
159
|
+
}
|
|
233
160
|
|
|
234
|
-
|
|
161
|
+
if (!rb_obj_is_kind_of(s->rbLayout, StructLayoutClass)) {
|
|
162
|
+
rb_raise(rb_eRuntimeError, "Invalid Struct layout");
|
|
235
163
|
}
|
|
164
|
+
|
|
165
|
+
Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
|
|
236
166
|
|
|
237
|
-
if (rbPointer
|
|
238
|
-
|
|
167
|
+
if (rbPointer != Qnil) {
|
|
168
|
+
s->pointer = MEMORY(rbPointer);
|
|
169
|
+
s->rbPointer = rbPointer;
|
|
170
|
+
} else {
|
|
171
|
+
s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
|
|
172
|
+
s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
|
|
239
173
|
}
|
|
240
|
-
|
|
241
|
-
s->
|
|
242
|
-
|
|
243
|
-
|
|
174
|
+
|
|
175
|
+
if (s->pointer->ops == NULL) {
|
|
176
|
+
VALUE name = rb_class_name(CLASS_OF(s->rbPointer));
|
|
177
|
+
rb_raise(rb_eRuntimeError, "No memory ops set for %s", StringValueCStr(name));
|
|
178
|
+
}
|
|
179
|
+
|
|
244
180
|
return self;
|
|
245
181
|
}
|
|
246
182
|
|
|
247
183
|
static void
|
|
248
184
|
struct_mark(Struct *s)
|
|
249
185
|
{
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
if (s->rbLayout != Qnil) {
|
|
254
|
-
rb_gc_mark(s->rbLayout);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
static void struct_free(Struct *s)
|
|
259
|
-
{
|
|
260
|
-
xfree(s);
|
|
186
|
+
rb_gc_mark(s->rbPointer);
|
|
187
|
+
rb_gc_mark(s->rbLayout);
|
|
261
188
|
}
|
|
262
189
|
|
|
263
190
|
static VALUE
|
|
@@ -268,54 +195,71 @@ struct_field(Struct* s, VALUE fieldName)
|
|
|
268
195
|
if (layout == NULL) {
|
|
269
196
|
rb_raise(rb_eRuntimeError, "layout not set for Struct");
|
|
270
197
|
}
|
|
198
|
+
|
|
271
199
|
rbField = rb_hash_aref(layout->rbFields, fieldName);
|
|
272
200
|
if (rbField == Qnil) {
|
|
273
|
-
VALUE str = rb_funcall2(fieldName,
|
|
201
|
+
VALUE str = rb_funcall2(fieldName, to_s, 0, NULL);
|
|
274
202
|
rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
|
|
275
203
|
}
|
|
204
|
+
|
|
276
205
|
return rbField;
|
|
277
206
|
}
|
|
278
207
|
|
|
279
|
-
static
|
|
280
|
-
|
|
208
|
+
static inline MemoryOp*
|
|
209
|
+
ptr_get_op(AbstractMemory* ptr, int type)
|
|
281
210
|
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Data_Get_Struct(self, Struct, s);
|
|
287
|
-
rbField = struct_field(s, fieldName);
|
|
288
|
-
f = FIELD_CAST(rbField);
|
|
289
|
-
|
|
290
|
-
switch (f->type) {
|
|
211
|
+
if (ptr == NULL || ptr->ops == NULL) {
|
|
212
|
+
return NULL;
|
|
213
|
+
}
|
|
214
|
+
switch (type) {
|
|
291
215
|
case NATIVE_INT8:
|
|
292
|
-
return
|
|
216
|
+
return ptr->ops->int8;
|
|
293
217
|
case NATIVE_UINT8:
|
|
294
|
-
return
|
|
218
|
+
return ptr->ops->uint8;
|
|
295
219
|
case NATIVE_INT16:
|
|
296
|
-
return
|
|
220
|
+
return ptr->ops->int16;
|
|
297
221
|
case NATIVE_UINT16:
|
|
298
|
-
return
|
|
222
|
+
return ptr->ops->uint16;
|
|
299
223
|
case NATIVE_INT32:
|
|
300
|
-
return
|
|
224
|
+
return ptr->ops->int32;
|
|
301
225
|
case NATIVE_UINT32:
|
|
302
|
-
return
|
|
226
|
+
return ptr->ops->uint32;
|
|
303
227
|
case NATIVE_INT64:
|
|
304
|
-
return
|
|
228
|
+
return ptr->ops->int64;
|
|
305
229
|
case NATIVE_UINT64:
|
|
306
|
-
return
|
|
230
|
+
return ptr->ops->uint64;
|
|
307
231
|
case NATIVE_FLOAT32:
|
|
308
|
-
return
|
|
232
|
+
return ptr->ops->float32;
|
|
309
233
|
case NATIVE_FLOAT64:
|
|
310
|
-
return
|
|
234
|
+
return ptr->ops->float64;
|
|
311
235
|
case NATIVE_POINTER:
|
|
312
|
-
return
|
|
236
|
+
return ptr->ops->pointer;
|
|
313
237
|
case NATIVE_STRING:
|
|
314
|
-
return
|
|
238
|
+
return ptr->ops->strptr;
|
|
315
239
|
default:
|
|
316
|
-
|
|
317
|
-
|
|
240
|
+
return NULL;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static VALUE
|
|
245
|
+
struct_get_field(VALUE self, VALUE fieldName)
|
|
246
|
+
{
|
|
247
|
+
Struct* s;
|
|
248
|
+
VALUE rbField;
|
|
249
|
+
StructField* f;
|
|
250
|
+
MemoryOp* op;
|
|
251
|
+
|
|
252
|
+
Data_Get_Struct(self, Struct, s);
|
|
253
|
+
rbField = struct_field(s, fieldName);
|
|
254
|
+
f = (StructField *) DATA_PTR(rbField);
|
|
255
|
+
|
|
256
|
+
op = ptr_get_op(s->pointer, f->type);
|
|
257
|
+
if (op != NULL) {
|
|
258
|
+
return (*op->get)(s->pointer, f->offset);
|
|
318
259
|
}
|
|
260
|
+
|
|
261
|
+
/* call up to the ruby code to fetch the value */
|
|
262
|
+
return rb_funcall2(rbField, get_id, 1, &s->rbPointer);
|
|
319
263
|
}
|
|
320
264
|
|
|
321
265
|
static VALUE
|
|
@@ -324,55 +268,24 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value)
|
|
|
324
268
|
Struct* s;
|
|
325
269
|
VALUE rbField;
|
|
326
270
|
StructField* f;
|
|
271
|
+
MemoryOp* op;
|
|
327
272
|
VALUE argv[2];
|
|
328
273
|
|
|
329
274
|
Data_Get_Struct(self, Struct, s);
|
|
330
275
|
rbField = struct_field(s, fieldName);
|
|
331
|
-
f =
|
|
276
|
+
f = (StructField *) DATA_PTR(rbField);
|
|
332
277
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
case NATIVE_UINT8:
|
|
338
|
-
ptr_put_uint8(s->pointer, f, value);
|
|
339
|
-
break;
|
|
340
|
-
case NATIVE_INT16:
|
|
341
|
-
ptr_put_int16(s->pointer, f, value);
|
|
342
|
-
break;
|
|
343
|
-
case NATIVE_UINT16:
|
|
344
|
-
ptr_put_uint16(s->pointer, f, value);
|
|
345
|
-
break;
|
|
346
|
-
case NATIVE_INT32:
|
|
347
|
-
ptr_put_int32(s->pointer, f, value);
|
|
348
|
-
break;
|
|
349
|
-
case NATIVE_UINT32:
|
|
350
|
-
ptr_put_uint32(s->pointer, f, value);
|
|
351
|
-
break;
|
|
352
|
-
case NATIVE_INT64:
|
|
353
|
-
ptr_put_int64(s->pointer, f, value);
|
|
354
|
-
break;
|
|
355
|
-
case NATIVE_UINT64:
|
|
356
|
-
ptr_put_uint64(s->pointer, f, value);
|
|
357
|
-
break;
|
|
358
|
-
case NATIVE_FLOAT32:
|
|
359
|
-
ptr_put_float32(s->pointer, f, value);
|
|
360
|
-
break;
|
|
361
|
-
case NATIVE_FLOAT64:
|
|
362
|
-
ptr_put_float64(s->pointer, f, value);
|
|
363
|
-
break;
|
|
364
|
-
case NATIVE_POINTER:
|
|
365
|
-
ptr_put_pointer(s->pointer, f, value);
|
|
366
|
-
break;
|
|
367
|
-
case NATIVE_STRING:
|
|
368
|
-
rb_raise(rb_eArgError, "Cannot set :string fields");
|
|
369
|
-
default:
|
|
370
|
-
/* call up to the ruby code to set the value */
|
|
371
|
-
argv[0] = s->rbPointer;
|
|
372
|
-
argv[1] = value;
|
|
373
|
-
rb_funcall2(rbField, putID, 2, argv);
|
|
374
|
-
break;
|
|
278
|
+
op = ptr_get_op(s->pointer, f->type);
|
|
279
|
+
if (op != NULL) {
|
|
280
|
+
(*op->put)(s->pointer, f->offset, value);
|
|
281
|
+
return self;
|
|
375
282
|
}
|
|
283
|
+
|
|
284
|
+
/* call up to the ruby code to set the value */
|
|
285
|
+
argv[0] = s->rbPointer;
|
|
286
|
+
argv[1] = value;
|
|
287
|
+
rb_funcall2(rbField, put_id, 2, argv);
|
|
288
|
+
|
|
376
289
|
return self;
|
|
377
290
|
}
|
|
378
291
|
|
|
@@ -381,14 +294,15 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
|
381
294
|
{
|
|
382
295
|
Struct* s;
|
|
383
296
|
|
|
384
|
-
if (!rb_obj_is_kind_of(pointer,
|
|
297
|
+
if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
|
|
385
298
|
rb_raise(rb_eArgError, "Invalid pointer");
|
|
386
299
|
}
|
|
387
300
|
|
|
388
301
|
Data_Get_Struct(self, Struct, s);
|
|
389
302
|
s->pointer = MEMORY(pointer);
|
|
390
303
|
s->rbPointer = pointer;
|
|
391
|
-
rb_ivar_set(self,
|
|
304
|
+
rb_ivar_set(self, pointer_var_id, pointer);
|
|
305
|
+
|
|
392
306
|
return self;
|
|
393
307
|
}
|
|
394
308
|
|
|
@@ -396,7 +310,9 @@ static VALUE
|
|
|
396
310
|
struct_get_pointer(VALUE self)
|
|
397
311
|
{
|
|
398
312
|
Struct* s;
|
|
313
|
+
|
|
399
314
|
Data_Get_Struct(self, Struct, s);
|
|
315
|
+
|
|
400
316
|
return s->rbPointer;
|
|
401
317
|
}
|
|
402
318
|
|
|
@@ -406,11 +322,13 @@ struct_set_layout(VALUE self, VALUE layout)
|
|
|
406
322
|
Struct* s;
|
|
407
323
|
Data_Get_Struct(self, Struct, s);
|
|
408
324
|
|
|
409
|
-
if (!rb_obj_is_kind_of(layout,
|
|
325
|
+
if (!rb_obj_is_kind_of(layout, StructLayoutClass)) {
|
|
410
326
|
rb_raise(rb_eArgError, "Invalid Struct layout");
|
|
411
327
|
}
|
|
328
|
+
|
|
412
329
|
Data_Get_Struct(layout, StructLayout, s->layout);
|
|
413
|
-
rb_ivar_set(self,
|
|
330
|
+
rb_ivar_set(self, layout_var_id, layout);
|
|
331
|
+
|
|
414
332
|
return self;
|
|
415
333
|
}
|
|
416
334
|
|
|
@@ -418,6 +336,7 @@ static VALUE
|
|
|
418
336
|
struct_get_layout(VALUE self)
|
|
419
337
|
{
|
|
420
338
|
Struct* s;
|
|
339
|
+
|
|
421
340
|
Data_Get_Struct(self, Struct, s);
|
|
422
341
|
|
|
423
342
|
return s->rbLayout;
|
|
@@ -427,16 +346,22 @@ static VALUE
|
|
|
427
346
|
struct_layout_allocate(VALUE klass)
|
|
428
347
|
{
|
|
429
348
|
StructLayout* layout;
|
|
430
|
-
|
|
349
|
+
VALUE obj;
|
|
350
|
+
|
|
351
|
+
obj = Data_Make_Struct(klass, StructLayout, struct_layout_mark, -1, layout);
|
|
352
|
+
layout->rbFields = Qnil;
|
|
353
|
+
|
|
354
|
+
return obj;
|
|
431
355
|
}
|
|
432
356
|
|
|
433
357
|
static VALUE
|
|
434
358
|
struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size, VALUE align)
|
|
435
359
|
{
|
|
436
360
|
StructLayout* layout;
|
|
361
|
+
int i;
|
|
437
362
|
|
|
438
363
|
Data_Get_Struct(self, StructLayout, layout);
|
|
439
|
-
layout->rbFields =
|
|
364
|
+
layout->rbFields = rb_hash_new();
|
|
440
365
|
layout->size = NUM2INT(size);
|
|
441
366
|
layout->align = NUM2INT(align);
|
|
442
367
|
|
|
@@ -445,6 +370,14 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
|
|
|
445
370
|
rb_iv_set(self, "@size", size);
|
|
446
371
|
rb_iv_set(self, "@align", align);
|
|
447
372
|
|
|
373
|
+
for (i = 0; i < RARRAY_LEN(field_names); ++i) {
|
|
374
|
+
VALUE name = RARRAY_PTR(field_names)[i];
|
|
375
|
+
VALUE field = rb_hash_aref(fields, name);
|
|
376
|
+
if (TYPE(field) != T_DATA || !rb_obj_is_kind_of(field, StructFieldClass)) {
|
|
377
|
+
rb_raise(rb_eArgError, "Invalid field");
|
|
378
|
+
}
|
|
379
|
+
rb_hash_aset(layout->rbFields, name, field);
|
|
380
|
+
}
|
|
448
381
|
return self;
|
|
449
382
|
}
|
|
450
383
|
|
|
@@ -454,6 +387,7 @@ struct_layout_aref(VALUE self, VALUE field)
|
|
|
454
387
|
StructLayout* layout;
|
|
455
388
|
|
|
456
389
|
Data_Get_Struct(self, StructLayout, layout);
|
|
390
|
+
|
|
457
391
|
return rb_hash_aref(layout->rbFields, field);
|
|
458
392
|
}
|
|
459
393
|
|
|
@@ -461,70 +395,71 @@ struct_layout_aref(VALUE self, VALUE field)
|
|
|
461
395
|
static void
|
|
462
396
|
struct_layout_mark(StructLayout *layout)
|
|
463
397
|
{
|
|
464
|
-
|
|
465
|
-
rb_gc_mark(layout->rbFields);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
static void
|
|
470
|
-
struct_layout_free(StructLayout *layout)
|
|
471
|
-
{
|
|
472
|
-
xfree(layout);
|
|
398
|
+
rb_gc_mark(layout->rbFields);
|
|
473
399
|
}
|
|
474
400
|
|
|
475
401
|
void
|
|
476
|
-
|
|
402
|
+
rbffi_Struct_Init(VALUE moduleFFI)
|
|
477
403
|
{
|
|
478
|
-
VALUE
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
rb_define_alloc_func(classStruct, struct_allocate);
|
|
486
|
-
rb_define_method(classStruct, "initialize", struct_initialize, -1);
|
|
487
|
-
|
|
488
|
-
rb_define_alias(rb_singleton_class(classStruct), "alloc_in", "new");
|
|
489
|
-
rb_define_alias(rb_singleton_class(classStruct), "alloc_out", "new");
|
|
490
|
-
rb_define_alias(rb_singleton_class(classStruct), "alloc_inout", "new");
|
|
491
|
-
rb_define_alias(rb_singleton_class(classStruct), "new_in", "new");
|
|
492
|
-
rb_define_alias(rb_singleton_class(classStruct), "new_out", "new");
|
|
493
|
-
rb_define_alias(rb_singleton_class(classStruct), "new_inout", "new");
|
|
404
|
+
VALUE klass, StructClass;
|
|
405
|
+
rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
|
|
406
|
+
rb_global_variable(&rbffi_StructClass);
|
|
407
|
+
|
|
408
|
+
StructLayoutClass = rb_define_class_under(moduleFFI, "StructLayout", rb_cObject);
|
|
409
|
+
rb_global_variable(&StructLayoutClass);
|
|
494
410
|
|
|
495
|
-
|
|
496
|
-
|
|
411
|
+
StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
|
|
412
|
+
rb_global_variable(&StructLayoutBuilderClass);
|
|
497
413
|
|
|
498
|
-
|
|
499
|
-
|
|
414
|
+
StructFieldClass = rb_define_class_under(StructLayoutBuilderClass, "Field", rb_cObject);
|
|
415
|
+
rb_global_variable(&StructFieldClass);
|
|
500
416
|
|
|
501
|
-
|
|
502
|
-
rb_define_method(
|
|
417
|
+
rb_define_alloc_func(StructClass, struct_allocate);
|
|
418
|
+
rb_define_method(StructClass, "initialize", struct_initialize, -1);
|
|
503
419
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
420
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
|
|
421
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
|
|
422
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_inout", "new");
|
|
423
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_in", "new");
|
|
424
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_out", "new");
|
|
425
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_inout", "new");
|
|
426
|
+
|
|
427
|
+
rb_define_method(StructClass, "pointer", struct_get_pointer, 0);
|
|
428
|
+
rb_define_private_method(StructClass, "pointer=", struct_set_pointer, 1);
|
|
429
|
+
|
|
430
|
+
rb_define_method(StructClass, "layout", struct_get_layout, 0);
|
|
431
|
+
rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
|
|
432
|
+
|
|
433
|
+
rb_define_method(StructClass, "[]", struct_get_field, 1);
|
|
434
|
+
rb_define_method(StructClass, "[]=", struct_put_field, 2);
|
|
507
435
|
|
|
508
|
-
rb_define_alloc_func(
|
|
509
|
-
rb_define_method(
|
|
510
|
-
rb_define_method(
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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");
|
|
516
451
|
to_ptr = rb_intern("to_ptr");
|
|
452
|
+
to_s = rb_intern("to_s");
|
|
517
453
|
SIZE_ID = rb_intern("SIZE");
|
|
518
454
|
ALIGN_ID = rb_intern("ALIGN");
|
|
455
|
+
TYPE_ID = rb_intern("TYPE");
|
|
519
456
|
#undef FIELD
|
|
520
457
|
#define FIELD(name, typeName, nativeType, T) do { \
|
|
521
458
|
typedef struct { char c; T v; } s; \
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
rb_define_const(klass, "SIZE", INT2NUM(sizeof(T)* 8)); \
|
|
527
|
-
rb_define_const(klass, "TYPE", INT2NUM(nativeType)); \
|
|
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)); \
|
|
528
463
|
} while(0)
|
|
529
464
|
|
|
530
465
|
FIELD(Signed8, int8, NATIVE_INT8, char);
|