ffi 0.3.5 → 0.4.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 +51 -1
- data/Rakefile +34 -26
- data/ext/ffi_c/AbstractMemory.c +73 -70
- data/ext/ffi_c/AbstractMemory.h +8 -4
- data/ext/ffi_c/AutoPointer.c +8 -9
- data/ext/ffi_c/AutoPointer.h +2 -2
- data/ext/ffi_c/Buffer.c +19 -20
- data/ext/ffi_c/Callback.c +85 -33
- data/ext/ffi_c/Callback.h +11 -5
- data/ext/ffi_c/{NativeLibrary.c → DynamicLibrary.c} +83 -16
- data/ext/ffi_c/{NativeLibrary.h → DynamicLibrary.h} +1 -1
- data/ext/ffi_c/Invoker.c +148 -192
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +26 -19
- data/ext/ffi_c/MemoryPointer.h +3 -3
- data/ext/ffi_c/NullPointer.c +49 -47
- data/ext/ffi_c/Platform.c +9 -10
- data/ext/ffi_c/Platform.h +1 -1
- data/ext/ffi_c/Pointer.c +52 -21
- data/ext/ffi_c/Pointer.h +8 -6
- data/ext/ffi_c/Struct.c +70 -61
- 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 +47 -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 +20 -43
- 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/lib/ffi.rb +10 -1
- 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 +78 -17
- 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/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 +19 -20
- metadata +29 -52
- data/ext/ffi_c/ffi.mk +0 -23
data/ext/ffi_c/Pointer.c
CHANGED
@@ -11,26 +11,25 @@ typedef struct Pointer {
|
|
11
11
|
VALUE parent;
|
12
12
|
} Pointer;
|
13
13
|
|
14
|
-
#define POINTER(obj)
|
14
|
+
#define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass)
|
15
15
|
|
16
|
-
VALUE
|
17
|
-
static VALUE classPointer = Qnil;
|
16
|
+
VALUE rbffi_PointerClass;
|
18
17
|
static void ptr_mark(Pointer* ptr);
|
19
18
|
|
20
19
|
VALUE
|
21
|
-
|
20
|
+
rbffi_Pointer_NewInstance(void* addr)
|
22
21
|
{
|
23
22
|
Pointer* p;
|
24
23
|
VALUE obj;
|
25
24
|
|
26
25
|
if (addr == NULL) {
|
27
|
-
return
|
26
|
+
return rbffi_NullPointerSingleton;
|
28
27
|
}
|
29
28
|
|
30
|
-
obj = Data_Make_Struct(
|
29
|
+
obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
|
31
30
|
p->memory.address = addr;
|
32
31
|
p->memory.size = LONG_MAX;
|
33
|
-
p->memory.ops = &
|
32
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
34
33
|
p->parent = Qnil;
|
35
34
|
|
36
35
|
return obj;
|
@@ -42,12 +41,43 @@ ptr_allocate(VALUE klass)
|
|
42
41
|
Pointer* p;
|
43
42
|
VALUE obj;
|
44
43
|
|
45
|
-
obj = Data_Make_Struct(
|
44
|
+
obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
|
46
45
|
p->parent = Qnil;
|
46
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
47
47
|
|
48
48
|
return obj;
|
49
49
|
}
|
50
50
|
|
51
|
+
static VALUE
|
52
|
+
ptr_initialize(int argc, VALUE* argv, VALUE self)
|
53
|
+
{
|
54
|
+
Pointer* p;
|
55
|
+
VALUE type, address;
|
56
|
+
|
57
|
+
Data_Get_Struct(self, Pointer, p);
|
58
|
+
|
59
|
+
switch (rb_scan_args(argc, argv, "11", &type, &address)) {
|
60
|
+
case 1:
|
61
|
+
p->memory.address = (void*)(uintptr_t) NUM2LL(type);
|
62
|
+
// FIXME set type_size to 1
|
63
|
+
break;
|
64
|
+
case 2:
|
65
|
+
p->memory.address = (void*)(uintptr_t) NUM2LL(address);
|
66
|
+
// FIXME set type_size to rbffi_type_size(type)
|
67
|
+
break;
|
68
|
+
default:
|
69
|
+
rb_raise(rb_eArgError, "Invalid arguments");
|
70
|
+
}
|
71
|
+
if (p->memory.address == NULL) {
|
72
|
+
p->memory.ops = &rbffi_NullPointerOps;
|
73
|
+
}
|
74
|
+
|
75
|
+
p->memory.size = LONG_MAX;
|
76
|
+
|
77
|
+
return self;
|
78
|
+
}
|
79
|
+
|
80
|
+
|
51
81
|
static VALUE
|
52
82
|
ptr_plus(VALUE self, VALUE offset)
|
53
83
|
{
|
@@ -59,11 +89,11 @@ ptr_plus(VALUE self, VALUE offset)
|
|
59
89
|
Data_Get_Struct(self, AbstractMemory, ptr);
|
60
90
|
checkBounds(ptr, off, 1);
|
61
91
|
|
62
|
-
retval = Data_Make_Struct(
|
92
|
+
retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
|
63
93
|
|
64
94
|
p->memory.address = ptr->address + off;
|
65
95
|
p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
|
66
|
-
p->memory.ops = &
|
96
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
67
97
|
p->parent = self;
|
68
98
|
|
69
99
|
return retval;
|
@@ -118,16 +148,17 @@ ptr_mark(Pointer* ptr)
|
|
118
148
|
}
|
119
149
|
|
120
150
|
void
|
121
|
-
|
151
|
+
rbffi_Pointer_Init(VALUE moduleFFI)
|
122
152
|
{
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
rb_define_method(
|
129
|
-
rb_define_method(
|
130
|
-
rb_define_method(
|
131
|
-
rb_define_method(
|
132
|
-
|
153
|
+
rbffi_PointerClass = rb_define_class_under(moduleFFI, "Pointer", rbffi_AbstractMemoryClass);
|
154
|
+
rb_global_variable(&rbffi_PointerClass);
|
155
|
+
|
156
|
+
rb_define_alloc_func(rbffi_PointerClass, ptr_allocate);
|
157
|
+
rb_define_method(rbffi_PointerClass, "initialize", ptr_initialize, -1);
|
158
|
+
rb_define_method(rbffi_PointerClass, "inspect", ptr_inspect, 0);
|
159
|
+
rb_define_method(rbffi_PointerClass, "+", ptr_plus, 1);
|
160
|
+
rb_define_method(rbffi_PointerClass, "null?", ptr_null_p, 0);
|
161
|
+
rb_define_method(rbffi_PointerClass, "address", ptr_address, 0);
|
162
|
+
rb_define_alias(rbffi_PointerClass, "to_i", "address");
|
163
|
+
rb_define_method(rbffi_PointerClass, "==", ptr_equals, 1);
|
133
164
|
}
|
data/ext/ffi_c/Pointer.h
CHANGED
@@ -6,14 +6,16 @@
|
|
6
6
|
extern "C" {
|
7
7
|
#endif
|
8
8
|
|
9
|
+
#include "AbstractMemory.h"
|
9
10
|
|
11
|
+
extern void rbffi_Pointer_Init(VALUE moduleFFI);
|
12
|
+
extern void rbffi_NullPointer_Init(VALUE moduleFFI);
|
13
|
+
extern VALUE rbffi_Pointer_NewInstance(void* addr);
|
14
|
+
extern VALUE rbffi_PointerClass;
|
15
|
+
extern VALUE rbffi_NullPointerClass;
|
16
|
+
extern VALUE rbffi_NullPointerSingleton;
|
17
|
+
extern MemoryOps rbffi_NullPointerOps;
|
10
18
|
|
11
|
-
extern void rb_FFI_Pointer_Init(void);
|
12
|
-
extern void rb_FFI_NullPointer_Init(void);
|
13
|
-
extern VALUE rb_FFI_Pointer_new(void* addr);
|
14
|
-
extern VALUE rb_FFI_Pointer_class;
|
15
|
-
extern VALUE rb_FFI_NullPointer_class;
|
16
|
-
extern VALUE rb_FFI_NullPointer_singleton;
|
17
19
|
|
18
20
|
#ifdef __cplusplus
|
19
21
|
}
|
data/ext/ffi_c/Struct.c
CHANGED
@@ -33,11 +33,11 @@ static void struct_mark(Struct *);
|
|
33
33
|
static void struct_layout_mark(StructLayout *);
|
34
34
|
static inline MemoryOp* ptr_get_op(AbstractMemory* ptr, int type);
|
35
35
|
|
36
|
-
VALUE
|
37
|
-
static VALUE
|
38
|
-
static VALUE
|
39
|
-
static ID
|
40
|
-
static ID
|
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
41
|
|
42
42
|
static VALUE
|
43
43
|
struct_field_allocate(VALUE klass)
|
@@ -58,15 +58,15 @@ struct_field_initialize(int argc, VALUE* argv, VALUE self)
|
|
58
58
|
nargs = rb_scan_args(argc, argv, "11", &offset, &info);
|
59
59
|
|
60
60
|
field->offset = NUM2UINT(offset);
|
61
|
-
if (rb_const_defined(CLASS_OF(self),
|
62
|
-
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));
|
63
63
|
} else {
|
64
64
|
field->type = ~0;
|
65
65
|
}
|
66
66
|
|
67
67
|
#ifdef notyet
|
68
|
-
field->size = NUM2UINT(rb_const_get(klass,
|
69
|
-
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));
|
70
70
|
#endif
|
71
71
|
rb_iv_set(self, "@off", offset);
|
72
72
|
rb_iv_set(self, "@info", info);
|
@@ -151,14 +151,14 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
151
151
|
|
152
152
|
/* Call up into ruby code to adjust the layout */
|
153
153
|
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,
|
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
157
|
} else {
|
158
158
|
rb_raise(rb_eRuntimeError, "No Struct layout configured");
|
159
159
|
}
|
160
160
|
|
161
|
-
if (!rb_obj_is_kind_of(s->rbLayout,
|
161
|
+
if (!rb_obj_is_kind_of(s->rbLayout, StructLayoutClass)) {
|
162
162
|
rb_raise(rb_eRuntimeError, "Invalid Struct layout");
|
163
163
|
}
|
164
164
|
|
@@ -168,7 +168,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self)
|
|
168
168
|
s->pointer = MEMORY(rbPointer);
|
169
169
|
s->rbPointer = rbPointer;
|
170
170
|
} else {
|
171
|
-
s->rbPointer =
|
171
|
+
s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
|
172
172
|
s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
|
173
173
|
}
|
174
174
|
|
@@ -198,7 +198,7 @@ struct_field(Struct* s, VALUE fieldName)
|
|
198
198
|
|
199
199
|
rbField = rb_hash_aref(layout->rbFields, fieldName);
|
200
200
|
if (rbField == Qnil) {
|
201
|
-
VALUE str = rb_funcall2(fieldName,
|
201
|
+
VALUE str = rb_funcall2(fieldName, to_s, 0, NULL);
|
202
202
|
rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
|
203
203
|
}
|
204
204
|
|
@@ -259,7 +259,7 @@ struct_get_field(VALUE self, VALUE fieldName)
|
|
259
259
|
}
|
260
260
|
|
261
261
|
/* call up to the ruby code to fetch the value */
|
262
|
-
return rb_funcall2(rbField,
|
262
|
+
return rb_funcall2(rbField, get_id, 1, &s->rbPointer);
|
263
263
|
}
|
264
264
|
|
265
265
|
static VALUE
|
@@ -284,7 +284,7 @@ struct_put_field(VALUE self, VALUE fieldName, VALUE value)
|
|
284
284
|
/* call up to the ruby code to set the value */
|
285
285
|
argv[0] = s->rbPointer;
|
286
286
|
argv[1] = value;
|
287
|
-
rb_funcall2(rbField,
|
287
|
+
rb_funcall2(rbField, put_id, 2, argv);
|
288
288
|
|
289
289
|
return self;
|
290
290
|
}
|
@@ -294,14 +294,14 @@ struct_set_pointer(VALUE self, VALUE pointer)
|
|
294
294
|
{
|
295
295
|
Struct* s;
|
296
296
|
|
297
|
-
if (!rb_obj_is_kind_of(pointer,
|
297
|
+
if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
|
298
298
|
rb_raise(rb_eArgError, "Invalid pointer");
|
299
299
|
}
|
300
300
|
|
301
301
|
Data_Get_Struct(self, Struct, s);
|
302
302
|
s->pointer = MEMORY(pointer);
|
303
303
|
s->rbPointer = pointer;
|
304
|
-
rb_ivar_set(self,
|
304
|
+
rb_ivar_set(self, pointer_var_id, pointer);
|
305
305
|
|
306
306
|
return self;
|
307
307
|
}
|
@@ -322,12 +322,12 @@ struct_set_layout(VALUE self, VALUE layout)
|
|
322
322
|
Struct* s;
|
323
323
|
Data_Get_Struct(self, Struct, s);
|
324
324
|
|
325
|
-
if (!rb_obj_is_kind_of(layout,
|
325
|
+
if (!rb_obj_is_kind_of(layout, StructLayoutClass)) {
|
326
326
|
rb_raise(rb_eArgError, "Invalid Struct layout");
|
327
327
|
}
|
328
328
|
|
329
329
|
Data_Get_Struct(layout, StructLayout, s->layout);
|
330
|
-
rb_ivar_set(self,
|
330
|
+
rb_ivar_set(self, layout_var_id, layout);
|
331
331
|
|
332
332
|
return self;
|
333
333
|
}
|
@@ -373,7 +373,7 @@ struct_layout_initialize(VALUE self, VALUE field_names, VALUE fields, VALUE size
|
|
373
373
|
for (i = 0; i < RARRAY_LEN(field_names); ++i) {
|
374
374
|
VALUE name = RARRAY_PTR(field_names)[i];
|
375
375
|
VALUE field = rb_hash_aref(fields, name);
|
376
|
-
if (TYPE(field) != T_DATA || !rb_obj_is_kind_of(field,
|
376
|
+
if (TYPE(field) != T_DATA || !rb_obj_is_kind_of(field, StructFieldClass)) {
|
377
377
|
rb_raise(rb_eArgError, "Invalid field");
|
378
378
|
}
|
379
379
|
rb_hash_aset(layout->rbFields, name, field);
|
@@ -399,57 +399,66 @@ struct_layout_mark(StructLayout *layout)
|
|
399
399
|
}
|
400
400
|
|
401
401
|
void
|
402
|
-
|
402
|
+
rbffi_Struct_Init(VALUE moduleFFI)
|
403
403
|
{
|
404
|
-
VALUE
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
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);
|
410
|
+
|
411
|
+
StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
|
412
|
+
rb_global_variable(&StructLayoutBuilderClass);
|
413
|
+
|
414
|
+
StructFieldClass = rb_define_class_under(StructLayoutBuilderClass, "Field", rb_cObject);
|
415
|
+
rb_global_variable(&StructFieldClass);
|
416
|
+
|
417
|
+
rb_define_alloc_func(StructClass, struct_allocate);
|
418
|
+
rb_define_method(StructClass, "initialize", struct_initialize, -1);
|
413
419
|
|
414
|
-
rb_define_alias(rb_singleton_class(
|
415
|
-
rb_define_alias(rb_singleton_class(
|
416
|
-
rb_define_alias(rb_singleton_class(
|
417
|
-
rb_define_alias(rb_singleton_class(
|
418
|
-
rb_define_alias(rb_singleton_class(
|
419
|
-
rb_define_alias(rb_singleton_class(
|
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");
|
420
426
|
|
421
|
-
rb_define_method(
|
422
|
-
rb_define_private_method(
|
427
|
+
rb_define_method(StructClass, "pointer", struct_get_pointer, 0);
|
428
|
+
rb_define_private_method(StructClass, "pointer=", struct_set_pointer, 1);
|
423
429
|
|
424
|
-
rb_define_method(
|
425
|
-
rb_define_private_method(
|
430
|
+
rb_define_method(StructClass, "layout", struct_get_layout, 0);
|
431
|
+
rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
|
426
432
|
|
427
|
-
rb_define_method(
|
428
|
-
rb_define_method(
|
433
|
+
rb_define_method(StructClass, "[]", struct_get_field, 1);
|
434
|
+
rb_define_method(StructClass, "[]=", struct_put_field, 2);
|
429
435
|
|
430
|
-
rb_define_alloc_func(
|
431
|
-
rb_define_method(
|
432
|
-
rb_define_method(
|
433
|
-
rb_define_method(
|
434
|
-
rb_define_method(
|
435
|
-
|
436
|
-
rb_define_alloc_func(
|
437
|
-
rb_define_method(
|
438
|
-
rb_define_method(
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
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");
|
444
451
|
to_ptr = rb_intern("to_ptr");
|
452
|
+
to_s = rb_intern("to_s");
|
445
453
|
SIZE_ID = rb_intern("SIZE");
|
446
454
|
ALIGN_ID = rb_intern("ALIGN");
|
455
|
+
TYPE_ID = rb_intern("TYPE");
|
447
456
|
#undef FIELD
|
448
457
|
#define FIELD(name, typeName, nativeType, T) do { \
|
449
458
|
typedef struct { char c; T v; } s; \
|
450
|
-
klass = rb_define_class_under(
|
451
|
-
rb_define_const(klass, "ALIGN", INT2NUM((sizeof(s) - sizeof(T))
|
452
|
-
rb_define_const(klass, "SIZE", INT2NUM(sizeof(T)
|
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))); \
|
453
462
|
rb_define_const(klass, "TYPE", INT2NUM(nativeType)); \
|
454
463
|
} while(0)
|
455
464
|
|
data/ext/ffi_c/Struct.h
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
extern "C" {
|
8
8
|
#endif
|
9
9
|
|
10
|
-
extern void
|
10
|
+
extern void rbffi_Struct_Init(VALUE ffiModule);
|
11
11
|
|
12
12
|
struct StructLayout;
|
13
13
|
typedef struct Struct {
|
@@ -17,7 +17,7 @@ extern "C" {
|
|
17
17
|
VALUE rbPointer;
|
18
18
|
} Struct;
|
19
19
|
|
20
|
-
extern VALUE
|
20
|
+
extern VALUE rbffi_StructClass;
|
21
21
|
#ifdef __cplusplus
|
22
22
|
}
|
23
23
|
#endif
|
data/ext/ffi_c/Type.c
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
#include <sys/param.h>
|
2
|
+
#include <sys/types.h>
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <ffi.h>
|
5
|
+
#include "rbffi.h"
|
6
|
+
#include "compat.h"
|
7
|
+
#include "Types.h"
|
8
|
+
#include "Type.h"
|
9
|
+
|
10
|
+
|
11
|
+
typedef struct BuiltinType_ {
|
12
|
+
Type type;
|
13
|
+
char* name;
|
14
|
+
} BuiltinType;
|
15
|
+
|
16
|
+
static void builtin_type_free(BuiltinType *);
|
17
|
+
|
18
|
+
VALUE rbffi_TypeClass = Qnil;
|
19
|
+
|
20
|
+
static VALUE classBuiltinType = Qnil;
|
21
|
+
|
22
|
+
static VALUE
|
23
|
+
type_allocate(VALUE klass)
|
24
|
+
{
|
25
|
+
Type* type;
|
26
|
+
VALUE obj = Data_Make_Struct(klass, Type, NULL, -1, type);
|
27
|
+
|
28
|
+
type->nativeType = -1;
|
29
|
+
type->size = 0;
|
30
|
+
type->alignment = 1;
|
31
|
+
|
32
|
+
return obj;
|
33
|
+
}
|
34
|
+
|
35
|
+
static VALUE
|
36
|
+
type_initialize(VALUE self, VALUE value)
|
37
|
+
{
|
38
|
+
Type* type;
|
39
|
+
Type* other;
|
40
|
+
|
41
|
+
Data_Get_Struct(self, Type, type);
|
42
|
+
|
43
|
+
if (FIXNUM_P(value)) {
|
44
|
+
type->nativeType = FIX2INT(value);
|
45
|
+
} else if (rb_obj_is_kind_of(value, rbffi_TypeClass)) {
|
46
|
+
Data_Get_Struct(value, Type, other);
|
47
|
+
type->nativeType = other->nativeType;
|
48
|
+
type->size = other->size;
|
49
|
+
type->alignment = other->alignment;
|
50
|
+
} else {
|
51
|
+
rb_raise(rb_eArgError, "wrong type");
|
52
|
+
}
|
53
|
+
|
54
|
+
return self;
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE
|
58
|
+
type_size(VALUE self)
|
59
|
+
{
|
60
|
+
Type *type;
|
61
|
+
|
62
|
+
Data_Get_Struct(self, Type, type);
|
63
|
+
|
64
|
+
return INT2FIX(type->size);
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE
|
68
|
+
type_alignment(VALUE self)
|
69
|
+
{
|
70
|
+
Type *type;
|
71
|
+
|
72
|
+
Data_Get_Struct(self, Type, type);
|
73
|
+
|
74
|
+
return INT2FIX(type->alignment);
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE
|
78
|
+
type_inspect(VALUE self)
|
79
|
+
{
|
80
|
+
char buf[256];
|
81
|
+
Type *type;
|
82
|
+
|
83
|
+
Data_Get_Struct(self, Type, type);
|
84
|
+
snprintf(buf, sizeof(buf), "#<FFI::Type:%p size=%d alignment=%d>",
|
85
|
+
type, type->size, type->alignment);
|
86
|
+
|
87
|
+
return rb_str_new2(buf);
|
88
|
+
}
|
89
|
+
|
90
|
+
static VALUE
|
91
|
+
enum_allocate(VALUE klass)
|
92
|
+
{
|
93
|
+
Type* type;
|
94
|
+
VALUE obj;
|
95
|
+
|
96
|
+
obj = Data_Make_Struct(klass, Type, NULL, -1, type);
|
97
|
+
type->nativeType = NATIVE_ENUM;
|
98
|
+
type->ffiType = &ffi_type_sint;
|
99
|
+
type->size = ffi_type_sint.size;
|
100
|
+
type->alignment = ffi_type_sint.alignment;
|
101
|
+
|
102
|
+
return obj;
|
103
|
+
}
|
104
|
+
|
105
|
+
int
|
106
|
+
rbffi_Type_GetIntValue(VALUE type)
|
107
|
+
{
|
108
|
+
if (rb_obj_is_kind_of(type, rbffi_TypeClass)) {
|
109
|
+
Type* t;
|
110
|
+
Data_Get_Struct(type, Type, t);
|
111
|
+
return t->nativeType;
|
112
|
+
} else {
|
113
|
+
rb_raise(rb_eArgError, "Invalid type argument");
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
static VALUE
|
118
|
+
builtin_type_new(VALUE klass, int nativeType, ffi_type* ffiType, const char* name)
|
119
|
+
{
|
120
|
+
BuiltinType* type;
|
121
|
+
VALUE obj = Data_Make_Struct(klass, BuiltinType, NULL, builtin_type_free, type);
|
122
|
+
|
123
|
+
type->name = strdup(name);
|
124
|
+
type->type.nativeType = nativeType;
|
125
|
+
type->type.ffiType = ffiType;
|
126
|
+
type->type.size = ffiType->size;
|
127
|
+
type->type.alignment = ffiType->alignment;
|
128
|
+
|
129
|
+
return obj;
|
130
|
+
}
|
131
|
+
|
132
|
+
static void
|
133
|
+
builtin_type_free(BuiltinType *type)
|
134
|
+
{
|
135
|
+
free(type->name);
|
136
|
+
xfree(type);
|
137
|
+
}
|
138
|
+
|
139
|
+
static VALUE
|
140
|
+
builtin_type_inspect(VALUE self)
|
141
|
+
{
|
142
|
+
char buf[256];
|
143
|
+
BuiltinType *type;
|
144
|
+
|
145
|
+
Data_Get_Struct(self, BuiltinType, type);
|
146
|
+
snprintf(buf, sizeof(buf), "#<FFI::Type::Builtin:%ssize=%d alignment=%d>",
|
147
|
+
type->name, type->type.size, type->type.alignment);
|
148
|
+
|
149
|
+
return rb_str_new2(buf);
|
150
|
+
}
|
151
|
+
|
152
|
+
void
|
153
|
+
rbffi_Type_Init(VALUE moduleFFI)
|
154
|
+
{
|
155
|
+
VALUE moduleNativeType;
|
156
|
+
VALUE classType = rbffi_TypeClass = rb_define_class_under(moduleFFI, "Type", rb_cObject);
|
157
|
+
VALUE classEnum = rb_define_class_under(moduleFFI, "Enum", classType);
|
158
|
+
classBuiltinType = rb_define_class_under(rbffi_TypeClass, "Builtin", rbffi_TypeClass);
|
159
|
+
moduleNativeType = rb_define_module_under(moduleFFI, "NativeType");
|
160
|
+
|
161
|
+
rb_global_variable(&rbffi_TypeClass);
|
162
|
+
rb_global_variable(&classBuiltinType);
|
163
|
+
rb_global_variable(&moduleNativeType);
|
164
|
+
|
165
|
+
rb_define_alloc_func(classType, type_allocate);
|
166
|
+
rb_define_method(classType, "initialize", type_initialize, 1);
|
167
|
+
rb_define_method(classType, "size", type_size, 0);
|
168
|
+
rb_define_method(classType, "alignment", type_alignment, 0);
|
169
|
+
rb_define_method(classBuiltinType, "inspect", type_inspect, 0);
|
170
|
+
|
171
|
+
// Make Type::Builtin non-allocatable
|
172
|
+
rb_undef_method(CLASS_OF(classBuiltinType), "new");
|
173
|
+
rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0);
|
174
|
+
|
175
|
+
rb_define_alloc_func(classEnum, enum_allocate);
|
176
|
+
|
177
|
+
rb_global_variable(&rbffi_TypeClass);
|
178
|
+
rb_global_variable(&classBuiltinType);
|
179
|
+
|
180
|
+
// Define all the builtin types
|
181
|
+
#define T(x, ffiType) do { \
|
182
|
+
VALUE t = Qnil; \
|
183
|
+
rb_define_const(classType, #x, t = builtin_type_new(classBuiltinType, NATIVE_##x, ffiType, #x)); \
|
184
|
+
rb_define_const(moduleNativeType, #x, t); \
|
185
|
+
rb_define_const(moduleFFI, "TYPE_" #x, t); \
|
186
|
+
} while(0)
|
187
|
+
|
188
|
+
T(VOID, &ffi_type_void);
|
189
|
+
T(INT8, &ffi_type_sint8);
|
190
|
+
T(UINT8, &ffi_type_uint8);
|
191
|
+
T(INT16, &ffi_type_sint16);
|
192
|
+
T(UINT16, &ffi_type_uint16);
|
193
|
+
T(INT32, &ffi_type_sint32);
|
194
|
+
T(UINT32, &ffi_type_uint32);
|
195
|
+
T(INT64, &ffi_type_sint64);
|
196
|
+
T(UINT64, &ffi_type_uint64);
|
197
|
+
T(FLOAT32, &ffi_type_float);
|
198
|
+
T(FLOAT64, &ffi_type_double);
|
199
|
+
T(POINTER, &ffi_type_pointer);
|
200
|
+
T(STRING, &ffi_type_pointer);
|
201
|
+
T(RBXSTRING, &ffi_type_pointer);
|
202
|
+
T(BUFFER_IN, &ffi_type_pointer);
|
203
|
+
T(BUFFER_OUT, &ffi_type_pointer);
|
204
|
+
T(BUFFER_INOUT, &ffi_type_pointer);
|
205
|
+
T(ENUM, &ffi_type_sint);
|
206
|
+
T(BOOL, &ffi_type_sint);
|
207
|
+
|
208
|
+
|
209
|
+
T(CHAR_ARRAY, &ffi_type_void);
|
210
|
+
T(VARARGS, &ffi_type_void);
|
211
|
+
|
212
|
+
|
213
|
+
if (sizeof(long) == 4) {
|
214
|
+
VALUE t = Qnil;
|
215
|
+
rb_define_const(classType, "LONG", t = builtin_type_new(classBuiltinType, NATIVE_INT32, &ffi_type_slong, "LONG"));
|
216
|
+
rb_define_const(moduleNativeType, "LONG", t);
|
217
|
+
rb_define_const(moduleFFI, "TYPE_LONG", t);
|
218
|
+
rb_define_const(classType, "ULONG", t = builtin_type_new(classBuiltinType, NATIVE_UINT32, &ffi_type_slong, "ULONG"));
|
219
|
+
rb_define_const(moduleNativeType, "ULONG", t);
|
220
|
+
rb_define_const(moduleFFI, "TYPE_ULONG", t);
|
221
|
+
} else {
|
222
|
+
VALUE t = Qnil;
|
223
|
+
rb_define_const(classType, "LONG", t = builtin_type_new(classBuiltinType, NATIVE_INT64, &ffi_type_slong, "LONG"));
|
224
|
+
rb_define_const(moduleNativeType, "LONG", t);
|
225
|
+
rb_define_const(moduleFFI, "TYPE_LONG", t);
|
226
|
+
rb_define_const(classType, "ULONG", t = builtin_type_new(classBuiltinType, NATIVE_UINT64, &ffi_type_slong, "ULONG"));
|
227
|
+
rb_define_const(moduleNativeType, "ULONG", t);
|
228
|
+
rb_define_const(moduleFFI, "TYPE_ULONG", t);
|
229
|
+
}
|
230
|
+
}
|