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
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#include <sys/param.h>
|
|
2
|
+
#include <sys/types.h>
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <stdbool.h>
|
|
6
|
+
#include <errno.h>
|
|
7
|
+
#include <ruby.h>
|
|
8
|
+
|
|
9
|
+
#include "LastError.h"
|
|
10
|
+
|
|
11
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
|
12
|
+
# include <pthread.h>
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
|
16
|
+
# define USE_PTHREAD_LOCAL
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
typedef struct ThreadData {
|
|
20
|
+
int td_errno;
|
|
21
|
+
} ThreadData;
|
|
22
|
+
|
|
23
|
+
#if defined(USE_PTHREAD_LOCAL)
|
|
24
|
+
static pthread_key_t threadDataKey;
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
static inline ThreadData* thread_data_get(void);
|
|
28
|
+
|
|
29
|
+
#if defined(USE_PTHREAD_LOCAL)
|
|
30
|
+
|
|
31
|
+
static ThreadData*
|
|
32
|
+
thread_data_init(void)
|
|
33
|
+
{
|
|
34
|
+
ThreadData* td = ALLOC_N(ThreadData, 1);
|
|
35
|
+
|
|
36
|
+
memset(td, 0, sizeof(*td));
|
|
37
|
+
pthread_setspecific(threadDataKey, td);
|
|
38
|
+
|
|
39
|
+
return td;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
static inline ThreadData*
|
|
44
|
+
thread_data_get(void)
|
|
45
|
+
{
|
|
46
|
+
ThreadData* td = pthread_getspecific(threadDataKey);
|
|
47
|
+
return td != NULL ? td : thread_data_init();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static void
|
|
51
|
+
thread_data_free(void *ptr)
|
|
52
|
+
{
|
|
53
|
+
xfree(ptr);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#else
|
|
57
|
+
static ID id_thread_data;
|
|
58
|
+
|
|
59
|
+
static ThreadData*
|
|
60
|
+
thread_data_init(void)
|
|
61
|
+
{
|
|
62
|
+
ThreadData* td;
|
|
63
|
+
VALUE obj;
|
|
64
|
+
|
|
65
|
+
obj = Data_Make_Struct(rb_cObject, ThreadData, NULL, -1, td);
|
|
66
|
+
rb_thread_local_aset(rb_thread_current(), id_thread_data, obj);
|
|
67
|
+
|
|
68
|
+
return td;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static inline ThreadData*
|
|
72
|
+
thread_data_get()
|
|
73
|
+
{
|
|
74
|
+
VALUE obj = rb_thread_local_aref(rb_thread_current(), id_thread_data);
|
|
75
|
+
|
|
76
|
+
if (obj != Qnil && TYPE(obj) == T_DATA) {
|
|
77
|
+
return (ThreadData *) DATA_PTR(obj);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return thread_data_init();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#endif
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
static VALUE
|
|
87
|
+
get_last_error(VALUE self)
|
|
88
|
+
{
|
|
89
|
+
return INT2NUM(thread_data_get()->td_errno);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
static VALUE
|
|
94
|
+
set_last_error(VALUE self, VALUE error)
|
|
95
|
+
{
|
|
96
|
+
|
|
97
|
+
#ifdef _WIN32
|
|
98
|
+
SetLastError(NUM2INT(error));
|
|
99
|
+
#else
|
|
100
|
+
errno = NUM2INT(error);
|
|
101
|
+
#endif
|
|
102
|
+
|
|
103
|
+
return Qnil;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
void
|
|
108
|
+
rbffi_save_errno(void)
|
|
109
|
+
{
|
|
110
|
+
int error = 0;
|
|
111
|
+
|
|
112
|
+
#ifdef _WIN32
|
|
113
|
+
error = GetLastError();
|
|
114
|
+
#else
|
|
115
|
+
error = errno;
|
|
116
|
+
#endif
|
|
117
|
+
|
|
118
|
+
thread_data_get()->td_errno = error;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
void
|
|
123
|
+
rbffi_LastError_Init(VALUE moduleFFI)
|
|
124
|
+
{
|
|
125
|
+
VALUE moduleError = rb_define_module_under(moduleFFI, "LastError");
|
|
126
|
+
|
|
127
|
+
rb_define_module_function(moduleError, "error", get_last_error, 0);
|
|
128
|
+
rb_define_module_function(moduleError, "error=", set_last_error, 1);
|
|
129
|
+
|
|
130
|
+
#if defined(USE_PTHREAD_LOCAL)
|
|
131
|
+
pthread_key_create(&threadDataKey, thread_data_free);
|
|
132
|
+
#else
|
|
133
|
+
id_thread_data = rb_intern("ffi_thread_local_data");
|
|
134
|
+
#endif /* USE_PTHREAD_LOCAL */
|
|
135
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#ifndef RBFFI_LASTERROR_H
|
|
2
|
+
#define RBFFI_LASTERROR_H
|
|
3
|
+
|
|
4
|
+
#ifdef __cplusplus
|
|
5
|
+
extern "C" {
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
void rbffi_LastError_Init(VALUE moduleFFI);
|
|
10
|
+
|
|
11
|
+
void rbffi_save_errno(void);
|
|
12
|
+
|
|
13
|
+
#ifdef __cplusplus
|
|
14
|
+
}
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
#endif /* RBFFI_LASTERROR_H */
|
|
18
|
+
|
data/ext/ffi_c/MemoryPointer.c
CHANGED
|
@@ -20,21 +20,26 @@ static void memptr_release(MemoryPointer* ptr);
|
|
|
20
20
|
static VALUE memptr_malloc(VALUE self, long size, long count, bool clear);
|
|
21
21
|
static VALUE memptr_free(VALUE self);
|
|
22
22
|
|
|
23
|
-
VALUE
|
|
24
|
-
|
|
25
|
-
#define MEMPTR(obj) ((MemoryPointer *)
|
|
23
|
+
VALUE rbffi_MemoryPointerClass;
|
|
24
|
+
|
|
25
|
+
#define MEMPTR(obj) ((MemoryPointer *) rbffi_AbstractMemory_Cast(obj, rbffi_MemoryPointerClass))
|
|
26
|
+
|
|
27
|
+
static ID plus_id = 0;
|
|
26
28
|
|
|
27
29
|
VALUE
|
|
28
|
-
|
|
30
|
+
rbffi_MemoryPointer_NewInstance(long size, long count, bool clear)
|
|
29
31
|
{
|
|
30
|
-
return memptr_malloc(memptr_allocate(
|
|
32
|
+
return memptr_malloc(memptr_allocate(rbffi_MemoryPointerClass), size, count, clear);
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
static VALUE
|
|
34
36
|
memptr_allocate(VALUE klass)
|
|
35
37
|
{
|
|
36
38
|
MemoryPointer* p;
|
|
37
|
-
|
|
39
|
+
VALUE obj = Data_Make_Struct(klass, MemoryPointer, NULL, memptr_release, p);
|
|
40
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
|
41
|
+
|
|
42
|
+
return obj;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
static VALUE
|
|
@@ -42,12 +47,14 @@ memptr_initialize(int argc, VALUE* argv, VALUE self)
|
|
|
42
47
|
{
|
|
43
48
|
VALUE size = Qnil, count = Qnil, clear = Qnil;
|
|
44
49
|
int nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
|
|
51
|
+
memptr_malloc(self, rbffi_type_size(size), nargs > 1 ? NUM2LONG(count) : 1,
|
|
52
|
+
RTEST(clear) || clear == Qnil);
|
|
47
53
|
|
|
48
54
|
if (rb_block_given_p()) {
|
|
49
|
-
return
|
|
55
|
+
return rb_ensure(rb_yield, self, memptr_free, self);
|
|
50
56
|
}
|
|
57
|
+
|
|
51
58
|
return self;
|
|
52
59
|
}
|
|
53
60
|
|
|
@@ -97,7 +104,7 @@ memptr_aref(VALUE self, VALUE which)
|
|
|
97
104
|
{
|
|
98
105
|
MemoryPointer* ptr = MEMPTR(self);
|
|
99
106
|
VALUE offset = INT2NUM(ptr->type_size * NUM2INT(which));
|
|
100
|
-
return rb_funcall2(self,
|
|
107
|
+
return rb_funcall2(self, plus_id, 1, &offset);
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
static VALUE
|
|
@@ -132,15 +139,18 @@ memptr_release(MemoryPointer* ptr)
|
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
void
|
|
135
|
-
|
|
142
|
+
rbffi_MemoryPointer_Init(VALUE moduleFFI)
|
|
136
143
|
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
rb_define_method(
|
|
142
|
-
rb_define_method(
|
|
143
|
-
rb_define_method(
|
|
144
|
-
rb_define_method(
|
|
145
|
-
rb_define_method(
|
|
144
|
+
rbffi_MemoryPointerClass = rb_define_class_under(moduleFFI, "MemoryPointer", rbffi_PointerClass);
|
|
145
|
+
rb_global_variable(&rbffi_MemoryPointerClass);
|
|
146
|
+
|
|
147
|
+
rb_define_alloc_func(rbffi_MemoryPointerClass, memptr_allocate);
|
|
148
|
+
rb_define_method(rbffi_MemoryPointerClass, "initialize", memptr_initialize, -1);
|
|
149
|
+
rb_define_method(rbffi_MemoryPointerClass, "inspect", memptr_inspect, 0);
|
|
150
|
+
rb_define_method(rbffi_MemoryPointerClass, "autorelease=", memptr_autorelease, 1);
|
|
151
|
+
rb_define_method(rbffi_MemoryPointerClass, "free", memptr_free, 0);
|
|
152
|
+
rb_define_method(rbffi_MemoryPointerClass, "type_size", memptr_type_size, 0);
|
|
153
|
+
rb_define_method(rbffi_MemoryPointerClass, "[]", memptr_aref, 1);
|
|
154
|
+
|
|
155
|
+
plus_id = rb_intern("+");
|
|
146
156
|
}
|
data/ext/ffi_c/MemoryPointer.h
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
extern "C" {
|
|
10
10
|
#endif
|
|
11
11
|
|
|
12
|
-
extern void
|
|
13
|
-
extern VALUE
|
|
14
|
-
extern VALUE
|
|
12
|
+
extern void rbffi_MemoryPointer_Init(VALUE moduleFFI);
|
|
13
|
+
extern VALUE rbffi_MemoryPointerClass;
|
|
14
|
+
extern VALUE rbffi_MemoryPointer_NewInstance(long size, long count, bool clear);
|
|
15
15
|
#ifdef __cplusplus
|
|
16
16
|
}
|
|
17
17
|
#endif
|
data/ext/ffi_c/NullPointer.c
CHANGED
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
#include "AbstractMemory.h"
|
|
8
8
|
#include "Pointer.h"
|
|
9
9
|
|
|
10
|
-
static VALUE
|
|
11
|
-
static VALUE classNullPointer;
|
|
12
|
-
VALUE rb_FFI_NullPointer_class;
|
|
13
|
-
VALUE rb_FFI_NullPointer_singleton;
|
|
10
|
+
static VALUE NullPointerErrorClass;
|
|
14
11
|
|
|
15
|
-
VALUE
|
|
16
|
-
|
|
12
|
+
VALUE rbffi_NullPointerClass;
|
|
13
|
+
VALUE rbffi_NullPointerSingleton;
|
|
14
|
+
|
|
15
|
+
static VALUE
|
|
16
|
+
nullptr_allocate(VALUE klass)
|
|
17
17
|
{
|
|
18
18
|
AbstractMemory* p;
|
|
19
19
|
VALUE retval;
|
|
@@ -21,13 +21,29 @@ rb_FFI_NullPointer_allocate(VALUE klass)
|
|
|
21
21
|
retval = Data_Make_Struct(klass, AbstractMemory, NULL, -1, p);
|
|
22
22
|
p->address = 0;
|
|
23
23
|
p->size = 0;
|
|
24
|
+
p->ops = &rbffi_NullPointerOps;
|
|
25
|
+
|
|
24
26
|
return retval;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
static VALUE
|
|
28
30
|
nullptr_op(int argc, VALUE* argv, VALUE self)
|
|
29
31
|
{
|
|
30
|
-
rb_raise(
|
|
32
|
+
rb_raise(NullPointerErrorClass, "NULL Pointer access attempted");
|
|
33
|
+
return Qnil;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static VALUE
|
|
37
|
+
nullptr_op_get(AbstractMemory* ptr, long offset)
|
|
38
|
+
{
|
|
39
|
+
rb_raise(NullPointerErrorClass, "NULL Pointer access attempted");
|
|
40
|
+
return Qnil;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static void
|
|
44
|
+
nullptr_op_put(AbstractMemory* ptr, long offset, VALUE value)
|
|
45
|
+
{
|
|
46
|
+
rb_raise(NullPointerErrorClass, "NULL Pointer access attempted");
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
static VALUE
|
|
@@ -46,10 +62,13 @@ static VALUE
|
|
|
46
62
|
nullptr_equals(VALUE self, VALUE other)
|
|
47
63
|
{
|
|
48
64
|
AbstractMemory* p2;
|
|
49
|
-
|
|
65
|
+
|
|
66
|
+
if (!rb_obj_is_kind_of(other, rbffi_PointerClass)) {
|
|
50
67
|
rb_raise(rb_eArgError, "Comparing Pointer with non Pointer");
|
|
51
68
|
}
|
|
69
|
+
|
|
52
70
|
Data_Get_Struct(other, AbstractMemory, p2);
|
|
71
|
+
|
|
53
72
|
return p2->address == 0 ? Qtrue : Qfalse;
|
|
54
73
|
}
|
|
55
74
|
|
|
@@ -59,25 +78,44 @@ nullptr_address(VALUE self)
|
|
|
59
78
|
return INT2NUM(0);
|
|
60
79
|
}
|
|
61
80
|
|
|
81
|
+
static MemoryOp NullPointerMemoryOp = { nullptr_op_get, nullptr_op_put };
|
|
82
|
+
|
|
83
|
+
MemoryOps rbffi_NullPointerOps = {
|
|
84
|
+
.int8 = &NullPointerMemoryOp,
|
|
85
|
+
.uint8 = &NullPointerMemoryOp,
|
|
86
|
+
.int16 = &NullPointerMemoryOp,
|
|
87
|
+
.int16 = &NullPointerMemoryOp,
|
|
88
|
+
.int32 = &NullPointerMemoryOp,
|
|
89
|
+
.uint32 = &NullPointerMemoryOp,
|
|
90
|
+
.int64 = &NullPointerMemoryOp,
|
|
91
|
+
.uint64 = &NullPointerMemoryOp,
|
|
92
|
+
.float32 = &NullPointerMemoryOp,
|
|
93
|
+
.float64 = &NullPointerMemoryOp,
|
|
94
|
+
.pointer = &NullPointerMemoryOp,
|
|
95
|
+
.strptr = &NullPointerMemoryOp,
|
|
96
|
+
};
|
|
62
97
|
|
|
63
98
|
void
|
|
64
|
-
|
|
99
|
+
rbffi_NullPointer_Init(VALUE moduleFFI)
|
|
65
100
|
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
rb_define_method(
|
|
74
|
-
rb_define_method(
|
|
101
|
+
rbffi_NullPointerClass = rb_define_class_under(moduleFFI, "NullPointer", rbffi_PointerClass);
|
|
102
|
+
rb_global_variable(&rbffi_NullPointerClass);
|
|
103
|
+
|
|
104
|
+
NullPointerErrorClass = rb_define_class_under(moduleFFI, "NullPointerError", rb_eRuntimeError);
|
|
105
|
+
rb_global_variable(&NullPointerErrorClass);
|
|
106
|
+
|
|
107
|
+
rb_define_alloc_func(rbffi_NullPointerClass, nullptr_allocate);
|
|
108
|
+
rb_define_method(rbffi_NullPointerClass, "inspect", nullptr_inspect, 0);
|
|
109
|
+
rb_define_method(rbffi_NullPointerClass, "+", nullptr_op, -1);
|
|
110
|
+
rb_define_method(rbffi_NullPointerClass, "null?", nullptr_null_p, 0);
|
|
111
|
+
rb_define_method(rbffi_NullPointerClass, "address", nullptr_address, 0);
|
|
112
|
+
rb_define_method(rbffi_NullPointerClass, "==", nullptr_equals, 1);
|
|
75
113
|
|
|
76
114
|
#define NOP(name) \
|
|
77
|
-
rb_define_method(
|
|
78
|
-
rb_define_method(
|
|
79
|
-
rb_define_method(
|
|
80
|
-
rb_define_method(
|
|
115
|
+
rb_define_method(rbffi_NullPointerClass, "get_" #name, nullptr_op, -1); \
|
|
116
|
+
rb_define_method(rbffi_NullPointerClass, "put_" #name, nullptr_op, -1); \
|
|
117
|
+
rb_define_method(rbffi_NullPointerClass, "get_array_of_" #name, nullptr_op, -1); \
|
|
118
|
+
rb_define_method(rbffi_NullPointerClass, "put_array_of_" #name, nullptr_op, -1); \
|
|
81
119
|
|
|
82
120
|
|
|
83
121
|
NOP(int8); NOP(uint8); NOP(int16); NOP(uint16);
|
|
@@ -89,16 +127,17 @@ rb_FFI_NullPointer_Init()
|
|
|
89
127
|
|
|
90
128
|
#undef NOP
|
|
91
129
|
#define NOP(name) \
|
|
92
|
-
rb_define_method(
|
|
93
|
-
rb_define_method(
|
|
130
|
+
rb_define_method(rbffi_NullPointerClass, "get_" #name, nullptr_op, -1); \
|
|
131
|
+
rb_define_method(rbffi_NullPointerClass, "put_" #name, nullptr_op, -1);
|
|
94
132
|
|
|
95
133
|
NOP(string); NOP(bytes); NOP(pointer); NOP(callback);
|
|
96
134
|
|
|
97
|
-
rb_define_method(
|
|
98
|
-
rb_define_method(
|
|
135
|
+
rb_define_method(rbffi_NullPointerClass, "clear", nullptr_op, -1); \
|
|
136
|
+
rb_define_method(rbffi_NullPointerClass, "total", nullptr_op, -1);
|
|
99
137
|
|
|
100
138
|
// Create a singleton instance of NullPointer that can be shared
|
|
101
|
-
|
|
102
|
-
|
|
139
|
+
rbffi_NullPointerSingleton = nullptr_allocate(rbffi_NullPointerClass);
|
|
140
|
+
rb_global_variable(&rbffi_NullPointerSingleton);
|
|
141
|
+
rb_define_const(rbffi_PointerClass, "NULL", rbffi_NullPointerSingleton);
|
|
103
142
|
}
|
|
104
143
|
|
data/ext/ffi_c/Platform.c
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
#include <stdbool.h>
|
|
5
5
|
#include <ruby.h>
|
|
6
6
|
#include <ctype.h>
|
|
7
|
+
#include "endian.h"
|
|
7
8
|
#include "Platform.h"
|
|
8
9
|
|
|
9
|
-
static VALUE
|
|
10
|
+
static VALUE PlatformModule = Qnil;
|
|
10
11
|
|
|
11
12
|
/*
|
|
12
13
|
* Determine the cpu type at compile time - useful for MacOSX where the the
|
|
@@ -47,14 +48,12 @@ export_primitive_types(VALUE module)
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
void
|
|
50
|
-
|
|
51
|
+
rbffi_Platform_Init(VALUE moduleFFI)
|
|
51
52
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
rb_define_const(
|
|
55
|
-
rb_define_const(
|
|
56
|
-
rb_define_const(
|
|
57
|
-
|
|
58
|
-
export_primitive_types(platform);
|
|
59
|
-
modulePlatform = platform;
|
|
53
|
+
PlatformModule = rb_define_module_under(moduleFFI, "Platform");
|
|
54
|
+
rb_define_const(PlatformModule, "BYTE_ORDER", INT2FIX(BYTE_ORDER));
|
|
55
|
+
rb_define_const(PlatformModule, "LITTLE_ENDIAN", INT2FIX(LITTLE_ENDIAN));
|
|
56
|
+
rb_define_const(PlatformModule, "BIG_ENDIAN", INT2FIX(BIG_ENDIAN));
|
|
57
|
+
rb_define_const(PlatformModule, "CPU", rb_str_new2(CPU));
|
|
58
|
+
export_primitive_types(PlatformModule);
|
|
60
59
|
}
|
data/ext/ffi_c/Platform.h
CHANGED
data/ext/ffi_c/Pointer.c
CHANGED
|
@@ -11,35 +11,73 @@ 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
|
-
static void ptr_free(Pointer* ptr);
|
|
20
18
|
|
|
21
19
|
VALUE
|
|
22
|
-
|
|
20
|
+
rbffi_Pointer_NewInstance(void* addr)
|
|
23
21
|
{
|
|
24
22
|
Pointer* p;
|
|
25
|
-
VALUE
|
|
23
|
+
VALUE obj;
|
|
24
|
+
|
|
26
25
|
if (addr == NULL) {
|
|
27
|
-
return
|
|
26
|
+
return rbffi_NullPointerSingleton;
|
|
28
27
|
}
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
|
|
30
30
|
p->memory.address = addr;
|
|
31
31
|
p->memory.size = LONG_MAX;
|
|
32
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
|
32
33
|
p->parent = Qnil;
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
return obj;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
static VALUE
|
|
37
39
|
ptr_allocate(VALUE klass)
|
|
38
40
|
{
|
|
39
41
|
Pointer* p;
|
|
40
|
-
|
|
42
|
+
VALUE obj;
|
|
43
|
+
|
|
44
|
+
obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
|
|
45
|
+
p->parent = Qnil;
|
|
46
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
|
47
|
+
|
|
48
|
+
return obj;
|
|
41
49
|
}
|
|
42
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
|
+
|
|
43
81
|
static VALUE
|
|
44
82
|
ptr_plus(VALUE self, VALUE offset)
|
|
45
83
|
{
|
|
@@ -51,10 +89,11 @@ ptr_plus(VALUE self, VALUE offset)
|
|
|
51
89
|
Data_Get_Struct(self, AbstractMemory, ptr);
|
|
52
90
|
checkBounds(ptr, off, 1);
|
|
53
91
|
|
|
54
|
-
retval = Data_Make_Struct(
|
|
92
|
+
retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
|
|
55
93
|
|
|
56
94
|
p->memory.address = ptr->address + off;
|
|
57
95
|
p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
|
|
96
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
|
58
97
|
p->parent = self;
|
|
59
98
|
|
|
60
99
|
return retval;
|
|
@@ -76,7 +115,9 @@ static VALUE
|
|
|
76
115
|
ptr_null_p(VALUE self)
|
|
77
116
|
{
|
|
78
117
|
Pointer* ptr;
|
|
118
|
+
|
|
79
119
|
Data_Get_Struct(self, Pointer, ptr);
|
|
120
|
+
|
|
80
121
|
return ptr->memory.address == NULL ? Qtrue : Qfalse;
|
|
81
122
|
}
|
|
82
123
|
|
|
@@ -84,6 +125,7 @@ static VALUE
|
|
|
84
125
|
ptr_equals(VALUE self, VALUE other)
|
|
85
126
|
{
|
|
86
127
|
Pointer* ptr;
|
|
128
|
+
|
|
87
129
|
Data_Get_Struct(self, Pointer, ptr);
|
|
88
130
|
|
|
89
131
|
return ptr->memory.address == POINTER(other)->address ? Qtrue : Qfalse;
|
|
@@ -93,6 +135,7 @@ static VALUE
|
|
|
93
135
|
ptr_address(VALUE self)
|
|
94
136
|
{
|
|
95
137
|
Pointer* ptr;
|
|
138
|
+
|
|
96
139
|
Data_Get_Struct(self, Pointer, ptr);
|
|
97
140
|
|
|
98
141
|
return ULL2NUM((uintptr_t) ptr->memory.address);
|
|
@@ -101,27 +144,21 @@ ptr_address(VALUE self)
|
|
|
101
144
|
static void
|
|
102
145
|
ptr_mark(Pointer* ptr)
|
|
103
146
|
{
|
|
104
|
-
|
|
105
|
-
rb_gc_mark(ptr->parent);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
static void
|
|
110
|
-
ptr_free(Pointer* ptr)
|
|
111
|
-
{
|
|
112
|
-
xfree(ptr);
|
|
147
|
+
rb_gc_mark(ptr->parent);
|
|
113
148
|
}
|
|
114
149
|
|
|
115
150
|
void
|
|
116
|
-
|
|
151
|
+
rbffi_Pointer_Init(VALUE moduleFFI)
|
|
117
152
|
{
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
rb_define_alloc_func(
|
|
122
|
-
rb_define_method(
|
|
123
|
-
rb_define_method(
|
|
124
|
-
rb_define_method(
|
|
125
|
-
rb_define_method(
|
|
126
|
-
rb_define_method(
|
|
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);
|
|
127
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();
|
|
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
|
}
|