ffi 0.3.1 → 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 +38 -28
- data/ext/ffi_c/AbstractMemory.c +74 -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 +42 -24
- 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 +152 -192
- data/ext/ffi_c/LastError.c +135 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +27 -20
- data/ext/ffi_c/MemoryPointer.h +3 -3
- data/ext/ffi_c/NullPointer.c +51 -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 +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
|
@@ -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
|
-
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
|
+
}
|
data/ext/ffi_c/Type.h
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#ifndef _TYPE_H
|
|
2
|
+
#define _TYPE_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
#include <ffi.h>
|
|
6
|
+
|
|
7
|
+
#ifdef __cplusplus
|
|
8
|
+
extern "C" {
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
typedef struct Type_ {
|
|
13
|
+
NativeType nativeType;
|
|
14
|
+
ffi_type* ffiType;
|
|
15
|
+
int size;
|
|
16
|
+
int alignment;
|
|
17
|
+
} Type;
|
|
18
|
+
|
|
19
|
+
extern VALUE rbffi_TypeClass;
|
|
20
|
+
extern int rbffi_Type_GetIntValue(VALUE type);
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#ifdef __cplusplus
|
|
24
|
+
}
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#endif /* _TYPE_H */
|
|
28
|
+
|
data/ext/ffi_c/Types.c
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
#include <ruby.h>
|
|
2
2
|
#include "Pointer.h"
|
|
3
|
+
#include "rbffi.h"
|
|
4
|
+
#include "Callback.h"
|
|
3
5
|
#include "Types.h"
|
|
4
6
|
|
|
7
|
+
static ID id_find = 0;
|
|
8
|
+
|
|
5
9
|
ffi_type*
|
|
6
|
-
|
|
10
|
+
rbffi_NativeType_ToFFI(NativeType type)
|
|
7
11
|
{
|
|
8
12
|
switch (type) {
|
|
9
13
|
case NATIVE_VOID:
|
|
@@ -16,7 +20,9 @@ rb_FFI_NativeTypeToFFI(NativeType type)
|
|
|
16
20
|
return &ffi_type_sint16;
|
|
17
21
|
case NATIVE_UINT16:
|
|
18
22
|
return &ffi_type_uint16;
|
|
23
|
+
case NATIVE_BOOL:
|
|
19
24
|
case NATIVE_INT32:
|
|
25
|
+
case NATIVE_ENUM:
|
|
20
26
|
return &ffi_type_sint32;
|
|
21
27
|
case NATIVE_UINT32:
|
|
22
28
|
return &ffi_type_uint32;
|
|
@@ -34,6 +40,7 @@ rb_FFI_NativeTypeToFFI(NativeType type)
|
|
|
34
40
|
case NATIVE_BUFFER_IN:
|
|
35
41
|
case NATIVE_BUFFER_OUT:
|
|
36
42
|
case NATIVE_BUFFER_INOUT:
|
|
43
|
+
case NATIVE_CALLBACK:
|
|
37
44
|
return &ffi_type_pointer;
|
|
38
45
|
default:
|
|
39
46
|
return NULL;
|
|
@@ -41,9 +48,9 @@ rb_FFI_NativeTypeToFFI(NativeType type)
|
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
VALUE
|
|
44
|
-
|
|
51
|
+
rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
|
|
45
52
|
{
|
|
46
|
-
switch (type) {
|
|
53
|
+
switch (type->nativeType) {
|
|
47
54
|
case NATIVE_VOID:
|
|
48
55
|
return Qnil;
|
|
49
56
|
case NATIVE_INT8:
|
|
@@ -67,10 +74,45 @@ rb_FFI_NativeValueToRuby(NativeType type, const void* ptr)
|
|
|
67
74
|
case NATIVE_FLOAT64:
|
|
68
75
|
return rb_float_new(*(double *) ptr);
|
|
69
76
|
case NATIVE_STRING:
|
|
70
|
-
return rb_tainted_str_new2(*(char **) ptr);
|
|
77
|
+
return (*(char **)ptr) ? rb_tainted_str_new2(*(char **) ptr) : Qnil;
|
|
71
78
|
case NATIVE_POINTER:
|
|
72
|
-
return
|
|
79
|
+
return rbffi_Pointer_NewInstance(*(void **) ptr);
|
|
80
|
+
case NATIVE_BOOL:
|
|
81
|
+
return ((int) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
|
|
82
|
+
case NATIVE_ENUM:
|
|
83
|
+
{
|
|
84
|
+
VALUE enum_obj = rb_funcall(enums, id_find, 1, rbType);
|
|
85
|
+
if (enum_obj == Qnil) {
|
|
86
|
+
VALUE s = rb_inspect(rbType);
|
|
87
|
+
rb_raise(rb_eRuntimeError, "Unknown enumeration: %s", StringValueCStr(s));
|
|
88
|
+
}
|
|
89
|
+
return rb_funcall(enum_obj, id_find, 1, INT2NUM((unsigned int) *(ffi_arg *) ptr));
|
|
90
|
+
}
|
|
91
|
+
case NATIVE_CALLBACK: {
|
|
92
|
+
CallbackInfo* cbInfo;
|
|
93
|
+
VALUE argv[6];
|
|
94
|
+
VALUE funcptr = rbffi_Pointer_NewInstance(*(void **) ptr);
|
|
95
|
+
|
|
96
|
+
Data_Get_Struct(rbType, CallbackInfo, cbInfo);
|
|
97
|
+
argv[0] = funcptr;
|
|
98
|
+
argv[1] = cbInfo->rbParameterTypes;
|
|
99
|
+
argv[2] = ID2SYM(rb_intern("cb")); // just shove a dummy value
|
|
100
|
+
argv[3] = cbInfo->rbReturnType;
|
|
101
|
+
argv[4] = rb_str_new2("default");
|
|
102
|
+
argv[5] = Qnil;
|
|
103
|
+
|
|
104
|
+
return rb_class_new_instance(6, argv, rbffi_InvokerClass);
|
|
105
|
+
}
|
|
106
|
+
|
|
73
107
|
default:
|
|
74
|
-
rb_raise(rb_eRuntimeError, "Unknown type: %d", type);
|
|
108
|
+
rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
|
|
109
|
+
return Qnil;
|
|
75
110
|
}
|
|
76
111
|
}
|
|
112
|
+
|
|
113
|
+
void
|
|
114
|
+
rbffi_Types_Init(VALUE moduleFFI)
|
|
115
|
+
{
|
|
116
|
+
id_find = rb_intern("find");
|
|
117
|
+
}
|
|
118
|
+
|
data/ext/ffi_c/Types.h
CHANGED
|
@@ -25,6 +25,7 @@ typedef enum {
|
|
|
25
25
|
NATIVE_BUFFER_OUT,
|
|
26
26
|
NATIVE_BUFFER_INOUT,
|
|
27
27
|
NATIVE_CHAR_ARRAY,
|
|
28
|
+
NATIVE_BOOL,
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* An immutable string. Nul terminated, but only copies in to the native function
|
|
@@ -34,11 +35,16 @@ typedef enum {
|
|
|
34
35
|
NATIVE_RBXSTRING,
|
|
35
36
|
/** The function takes a variable number of arguments */
|
|
36
37
|
NATIVE_VARARGS,
|
|
38
|
+
/** A typedef-ed enum */
|
|
39
|
+
NATIVE_ENUM,
|
|
37
40
|
} NativeType;
|
|
38
41
|
|
|
39
42
|
#include <ffi.h>
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
#include "Type.h"
|
|
44
|
+
|
|
45
|
+
extern ffi_type* rbffi_NativeType_ToFFI(NativeType type);
|
|
46
|
+
VALUE rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums);
|
|
47
|
+
void rbffi_Types_Init(VALUE moduleFFI);
|
|
42
48
|
|
|
43
49
|
#ifdef __cplusplus
|
|
44
50
|
}
|
data/ext/ffi_c/endian.h
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#ifndef JFFI_ENDIAN_H
|
|
2
|
+
#define JFFI_ENDIAN_H
|
|
3
|
+
|
|
4
|
+
#include <sys/param.h>
|
|
5
|
+
#include <sys/types.h>
|
|
6
|
+
|
|
7
|
+
#ifdef __linux__
|
|
8
|
+
# include_next <endian.h>
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#ifdef __sun
|
|
12
|
+
# include <sys/byteorder.h>
|
|
13
|
+
# define LITTLE_ENDIAN 1234
|
|
14
|
+
# define BIG_ENDIAN 4321
|
|
15
|
+
# if defined(_BIG_ENDIAN)
|
|
16
|
+
# define BYTE_ORDER BIG_ENDIAN
|
|
17
|
+
# elif defined(_LITTLE_ENDIAN)
|
|
18
|
+
# define BYTE_ORDER LITTLE_ENDIAN
|
|
19
|
+
# else
|
|
20
|
+
# error "Cannot determine endian-ness"
|
|
21
|
+
# endif
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
#if defined(_AIX) && !defined(BYTE_ORDER)
|
|
25
|
+
# define LITTLE_ENDIAN 1234
|
|
26
|
+
# define BIG_ENDIAN 4321
|
|
27
|
+
# if defined(__BIG_ENDIAN__)
|
|
28
|
+
# define BYTE_ORDER BIG_ENDIAN
|
|
29
|
+
# elif defined(__LITTLE_ENDIAN__)
|
|
30
|
+
# define BYTE_ORDER LITTLE_ENDIAN
|
|
31
|
+
# else
|
|
32
|
+
# error "Cannot determine endian-ness"
|
|
33
|
+
# endif
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
|
|
37
|
+
# error "Cannot determine the endian-ness of this platform"
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
#endif /* JFFI_ENDIAN_H */
|