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/AutoPointer.c
CHANGED
@@ -17,7 +17,7 @@ static void autoptr_mark(AutoPointer* ptr);
|
|
17
17
|
static VALUE autoptr_allocate(VALUE klass);
|
18
18
|
static VALUE autoptr_set_parent(VALUE self, VALUE parent);
|
19
19
|
|
20
|
-
VALUE
|
20
|
+
VALUE rbffi_AutoPointerClass = Qnil;
|
21
21
|
|
22
22
|
static VALUE
|
23
23
|
autoptr_allocate(VALUE klass)
|
@@ -25,7 +25,7 @@ autoptr_allocate(VALUE klass)
|
|
25
25
|
AutoPointer* p;
|
26
26
|
VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, -1, p);
|
27
27
|
p->parent = Qnil;
|
28
|
-
p->memory.ops = &
|
28
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
29
29
|
|
30
30
|
return obj;
|
31
31
|
}
|
@@ -34,7 +34,7 @@ static VALUE
|
|
34
34
|
autoptr_set_parent(VALUE self, VALUE parent)
|
35
35
|
{
|
36
36
|
AutoPointer* p;
|
37
|
-
AbstractMemory* ptr =
|
37
|
+
AbstractMemory* ptr = rbffi_AbstractMemory_Cast(parent, rbffi_PointerClass);
|
38
38
|
|
39
39
|
Data_Get_Struct(self, AutoPointer, p);
|
40
40
|
p->memory = *ptr;
|
@@ -50,12 +50,11 @@ autoptr_mark(AutoPointer* ptr)
|
|
50
50
|
}
|
51
51
|
|
52
52
|
void
|
53
|
-
|
53
|
+
rbffi_AutoPointer_Init(VALUE moduleFFI)
|
54
54
|
{
|
55
|
-
|
56
|
-
|
57
|
-
rb_global_variable(&rb_FFI_AutoPointer_class);
|
55
|
+
rbffi_AutoPointerClass = rb_define_class_under(moduleFFI, "AutoPointer", rbffi_PointerClass);
|
56
|
+
rb_global_variable(&rbffi_AutoPointerClass);
|
58
57
|
|
59
|
-
rb_define_alloc_func(
|
60
|
-
rb_define_protected_method(
|
58
|
+
rb_define_alloc_func(rbffi_AutoPointerClass, autoptr_allocate);
|
59
|
+
rb_define_protected_method(rbffi_AutoPointerClass, "parent=", autoptr_set_parent, 1);
|
61
60
|
}
|
data/ext/ffi_c/AutoPointer.h
CHANGED
data/ext/ffi_c/Buffer.c
CHANGED
@@ -18,8 +18,8 @@ static void buffer_release(Buffer* ptr);
|
|
18
18
|
static void buffer_mark(Buffer* ptr);
|
19
19
|
static VALUE buffer_free(VALUE self);
|
20
20
|
|
21
|
-
static VALUE
|
22
|
-
#define BUFFER(obj) ((Buffer *)
|
21
|
+
static VALUE BufferClass = Qnil;
|
22
|
+
#define BUFFER(obj) ((Buffer *) rbffi_AbstractMemory_Cast((obj), BufferClass))
|
23
23
|
|
24
24
|
static VALUE
|
25
25
|
buffer_allocate(VALUE klass)
|
@@ -29,7 +29,7 @@ buffer_allocate(VALUE klass)
|
|
29
29
|
|
30
30
|
obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
|
31
31
|
buffer->parent = Qnil;
|
32
|
-
buffer->memory.ops = &
|
32
|
+
buffer->memory.ops = &rbffi_AbstractMemoryOps;
|
33
33
|
|
34
34
|
return obj;
|
35
35
|
}
|
@@ -55,7 +55,7 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
|
|
55
55
|
Data_Get_Struct(self, Buffer, p);
|
56
56
|
|
57
57
|
nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
|
58
|
-
p->type_size =
|
58
|
+
p->type_size = rbffi_type_size(size);
|
59
59
|
p->memory.size = p->type_size * (nargs > 1 ? NUM2LONG(count) : 1);
|
60
60
|
|
61
61
|
p->storage = malloc(p->memory.size + 7);
|
@@ -66,7 +66,7 @@ buffer_initialize(int argc, VALUE* argv, VALUE self)
|
|
66
66
|
/* ensure the memory is aligned on at least a 8 byte boundary */
|
67
67
|
p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
|
68
68
|
|
69
|
-
if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
|
69
|
+
if (nargs > 2 && (RTEST(clear) || clear == Qnil) && p->memory.size > 0) {
|
70
70
|
memset(p->memory.address, 0, p->memory.size);
|
71
71
|
}
|
72
72
|
|
@@ -93,10 +93,10 @@ buffer_plus(VALUE self, VALUE offset)
|
|
93
93
|
|
94
94
|
checkBounds(&ptr->memory, off, 1);
|
95
95
|
|
96
|
-
retval = Data_Make_Struct(
|
96
|
+
retval = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, p);
|
97
97
|
p->memory.address = ptr->memory.address + off;
|
98
98
|
p->memory.size = ptr->memory.size - off;
|
99
|
-
p->memory.ops = &
|
99
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
100
100
|
p->parent = self;
|
101
101
|
|
102
102
|
return retval;
|
@@ -152,21 +152,20 @@ buffer_mark(Buffer* ptr)
|
|
152
152
|
}
|
153
153
|
|
154
154
|
void
|
155
|
-
|
155
|
+
rbffi_Buffer_Init(VALUE moduleFFI)
|
156
156
|
{
|
157
|
-
|
158
|
-
classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
|
157
|
+
BufferClass = rb_define_class_under(moduleFFI, "Buffer", rbffi_AbstractMemoryClass);
|
159
158
|
|
160
|
-
rb_global_variable(&
|
161
|
-
rb_define_alloc_func(
|
159
|
+
rb_global_variable(&BufferClass);
|
160
|
+
rb_define_alloc_func(BufferClass, buffer_allocate);
|
162
161
|
|
163
|
-
rb_define_singleton_method(
|
164
|
-
rb_define_singleton_method(
|
165
|
-
rb_define_singleton_method(
|
162
|
+
rb_define_singleton_method(BufferClass, "alloc_inout", buffer_alloc_inout, -1);
|
163
|
+
rb_define_singleton_method(BufferClass, "alloc_out", buffer_alloc_inout, -1);
|
164
|
+
rb_define_singleton_method(BufferClass, "alloc_in", buffer_alloc_inout, -1);
|
166
165
|
|
167
|
-
rb_define_method(
|
168
|
-
rb_define_method(
|
169
|
-
rb_define_method(
|
170
|
-
rb_define_method(
|
171
|
-
rb_define_method(
|
166
|
+
rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
|
167
|
+
rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
|
168
|
+
rb_define_method(BufferClass, "type_size", buffer_type_size, 0);
|
169
|
+
rb_define_method(BufferClass, "[]", buffer_aref, 1);
|
170
|
+
rb_define_method(BufferClass, "+", buffer_plus, 1);
|
172
171
|
}
|
data/ext/ffi_c/Callback.c
CHANGED
@@ -10,11 +10,12 @@
|
|
10
10
|
#include "MemoryPointer.h"
|
11
11
|
#include "Callback.h"
|
12
12
|
#include "Types.h"
|
13
|
+
#include "Type.h"
|
13
14
|
#include "rbffi.h"
|
14
15
|
#include "compat.h"
|
15
16
|
#include "extconf.h"
|
16
17
|
|
17
|
-
|
18
|
+
static void cbinfo_mark(CallbackInfo* cbInfo);
|
18
19
|
static void cbinfo_free(CallbackInfo *);
|
19
20
|
|
20
21
|
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
@@ -25,17 +26,25 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
|
25
26
|
void* user_data, void* code);
|
26
27
|
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
27
28
|
|
28
|
-
static VALUE
|
29
|
-
static VALUE
|
30
|
-
static ID
|
29
|
+
static VALUE CallbackInfoClass = Qnil;
|
30
|
+
static VALUE NativeCallbackClass = Qnil;
|
31
|
+
static ID id_call = Qnil, id_cbtable = Qnil;
|
31
32
|
|
32
|
-
VALUE
|
33
|
+
VALUE rbffi_CallbackInfoClass = Qnil;
|
33
34
|
|
34
35
|
static VALUE
|
35
36
|
cbinfo_allocate(VALUE klass)
|
36
37
|
{
|
37
38
|
CallbackInfo* cbInfo;
|
38
|
-
|
39
|
+
VALUE obj = Data_Make_Struct(klass, CallbackInfo, cbinfo_mark, cbinfo_free, cbInfo);
|
40
|
+
|
41
|
+
cbInfo->type.ffiType = &ffi_type_pointer;
|
42
|
+
cbInfo->type.size = ffi_type_pointer.size;
|
43
|
+
cbInfo->type.alignment = ffi_type_pointer.alignment;
|
44
|
+
cbInfo->type.nativeType = NATIVE_CALLBACK;
|
45
|
+
cbInfo->rbReturnType = Qnil;
|
46
|
+
|
47
|
+
return obj;
|
39
48
|
}
|
40
49
|
|
41
50
|
static VALUE
|
@@ -47,25 +56,37 @@ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
|
|
47
56
|
int i;
|
48
57
|
|
49
58
|
Check_Type(rbParamTypes, T_ARRAY);
|
59
|
+
|
60
|
+
|
50
61
|
paramCount = RARRAY_LEN(rbParamTypes);
|
51
62
|
|
52
63
|
Data_Get_Struct(self, CallbackInfo, cbInfo);
|
53
64
|
cbInfo->parameterCount = paramCount;
|
54
|
-
cbInfo->parameterTypes = xcalloc(paramCount, sizeof(
|
65
|
+
cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
|
55
66
|
cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
|
56
|
-
cbInfo->returnType
|
67
|
+
Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
|
68
|
+
cbInfo->rbReturnType = rbReturnType;
|
69
|
+
cbInfo->rbParameterTypes = rbParamTypes;
|
57
70
|
|
58
71
|
for (i = 0; i < paramCount; ++i) {
|
59
|
-
|
60
|
-
|
72
|
+
VALUE entry = rb_ary_entry(rbParamTypes, i);
|
73
|
+
if (!rb_obj_is_kind_of(entry, rbffi_TypeClass)) {
|
74
|
+
rb_raise(rb_eTypeError, "Invalid parameter type");
|
75
|
+
}
|
76
|
+
Data_Get_Struct(entry, Type, cbInfo->parameterTypes[i]);
|
77
|
+
cbInfo->ffiParameterTypes[i] = cbInfo->parameterTypes[i]->ffiType;
|
61
78
|
if (cbInfo->ffiParameterTypes[i] == NULL) {
|
62
|
-
rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]);
|
79
|
+
rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
|
63
80
|
}
|
64
81
|
}
|
65
82
|
|
66
|
-
|
83
|
+
if (!rb_obj_is_kind_of(rbReturnType, rbffi_TypeClass)) {
|
84
|
+
rb_raise(rb_eTypeError, "Invalid return type");
|
85
|
+
}
|
86
|
+
|
87
|
+
cbInfo->ffiReturnType = cbInfo->returnType->ffiType;
|
67
88
|
if (cbInfo->ffiReturnType == NULL) {
|
68
|
-
rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
|
89
|
+
rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
|
69
90
|
}
|
70
91
|
#if defined(_WIN32) && defined(notyet)
|
71
92
|
cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
@@ -87,6 +108,13 @@ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
|
|
87
108
|
return self;
|
88
109
|
}
|
89
110
|
|
111
|
+
static void
|
112
|
+
cbinfo_mark(CallbackInfo* cbInfo)
|
113
|
+
{
|
114
|
+
rb_gc_mark(cbInfo->rbReturnType);
|
115
|
+
rb_gc_mark(cbInfo->rbParameterTypes);
|
116
|
+
}
|
117
|
+
|
90
118
|
static void
|
91
119
|
cbinfo_free(CallbackInfo* cbInfo)
|
92
120
|
{
|
@@ -127,7 +155,7 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
127
155
|
rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
|
128
156
|
for (i = 0; i < cbInfo->parameterCount; ++i) {
|
129
157
|
VALUE param;
|
130
|
-
switch (cbInfo->parameterTypes[i]) {
|
158
|
+
switch (cbInfo->parameterTypes[i]->nativeType) {
|
131
159
|
case NATIVE_INT8:
|
132
160
|
param = INT2NUM(*(int8_t *) parameters[i]);
|
133
161
|
break;
|
@@ -162,7 +190,14 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
162
190
|
param = rb_tainted_str_new2(*(char **) parameters[i]);
|
163
191
|
break;
|
164
192
|
case NATIVE_POINTER:
|
165
|
-
param =
|
193
|
+
param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
|
194
|
+
break;
|
195
|
+
case NATIVE_BOOL:
|
196
|
+
param = (*(void **) parameters[i]) ? Qtrue : Qfalse;
|
197
|
+
break;
|
198
|
+
case NATIVE_CALLBACK:
|
199
|
+
param = rbffi_NativeValue_ToRuby(cbInfo->parameterTypes[i],
|
200
|
+
rb_ary_entry(cbInfo->rbParameterTypes, i), parameters[i], Qnil);
|
166
201
|
break;
|
167
202
|
default:
|
168
203
|
param = Qnil;
|
@@ -170,10 +205,10 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
170
205
|
}
|
171
206
|
rbParams[i] = param;
|
172
207
|
}
|
173
|
-
rbReturnValue = rb_funcall2(cb->rbProc,
|
208
|
+
rbReturnValue = rb_funcall2(cb->rbProc, id_call, cbInfo->parameterCount, rbParams);
|
174
209
|
if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
|
175
210
|
memset(retval, 0, cbInfo->ffiReturnType->size);
|
176
|
-
} else switch (cbInfo->returnType) {
|
211
|
+
} else switch (cbInfo->returnType->nativeType) {
|
177
212
|
case NATIVE_INT8:
|
178
213
|
case NATIVE_INT16:
|
179
214
|
case NATIVE_INT32:
|
@@ -197,14 +232,30 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
197
232
|
*((double *) retval) = NUM2DBL(rbReturnValue);
|
198
233
|
break;
|
199
234
|
case NATIVE_POINTER:
|
200
|
-
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue,
|
235
|
+
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
|
201
236
|
*((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
|
202
237
|
} else {
|
203
238
|
// Default to returning NULL if not a value pointer object. handles nil case as well
|
204
239
|
*((void **) retval) = NULL;
|
205
240
|
}
|
206
241
|
break;
|
242
|
+
case NATIVE_BOOL:
|
243
|
+
*((ffi_sarg *) retval) = TYPE(rbReturnValue) == T_TRUE ? 1 : 0;
|
244
|
+
break;
|
245
|
+
case NATIVE_CALLBACK:
|
246
|
+
if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
|
247
|
+
VALUE callback;
|
248
|
+
|
249
|
+
callback = rbffi_NativeCallback_ForProc(rbReturnValue, cbInfo->rbReturnType);
|
250
|
+
|
251
|
+
*((void **) retval) = ((NativeCallback *) DATA_PTR(callback))->code;
|
252
|
+
} else {
|
253
|
+
*((void **) retval) = NULL;
|
254
|
+
}
|
255
|
+
break;
|
256
|
+
|
207
257
|
default:
|
258
|
+
*((ffi_arg *) retval) = 0;
|
208
259
|
break;
|
209
260
|
}
|
210
261
|
}
|
@@ -223,7 +274,7 @@ native_callback_allocate(VALUE klass)
|
|
223
274
|
}
|
224
275
|
|
225
276
|
VALUE
|
226
|
-
|
277
|
+
rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
|
227
278
|
{
|
228
279
|
NativeCallback* closure = NULL;
|
229
280
|
CallbackInfo* cbInfo;
|
@@ -231,7 +282,7 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
|
|
231
282
|
ffi_status status;
|
232
283
|
|
233
284
|
Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
|
234
|
-
obj = Data_Make_Struct(
|
285
|
+
obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
|
235
286
|
closure->cbInfo = cbInfo;
|
236
287
|
closure->rbProc = rbProc;
|
237
288
|
closure->rbCallbackInfo = rbCallbackInfo;
|
@@ -251,19 +302,19 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
|
|
251
302
|
}
|
252
303
|
|
253
304
|
VALUE
|
254
|
-
|
305
|
+
rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
|
255
306
|
{
|
256
307
|
VALUE callback;
|
257
|
-
VALUE cbTable = RTEST(rb_ivar_defined(proc,
|
308
|
+
VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
|
258
309
|
if (cbTable == Qnil) {
|
259
310
|
cbTable = rb_hash_new();
|
260
|
-
rb_ivar_set(proc,
|
311
|
+
rb_ivar_set(proc, id_cbtable, cbTable);
|
261
312
|
}
|
262
313
|
callback = rb_hash_aref(cbTable, cbInfo);
|
263
314
|
if (callback != Qnil) {
|
264
315
|
return callback;
|
265
316
|
}
|
266
|
-
callback =
|
317
|
+
callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
|
267
318
|
rb_hash_aset(cbTable, cbInfo, callback);
|
268
319
|
return callback;
|
269
320
|
}
|
@@ -307,16 +358,17 @@ ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
|
307
358
|
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
308
359
|
|
309
360
|
void
|
310
|
-
|
361
|
+
rbffi_Callback_Init(VALUE moduleFFI)
|
311
362
|
{
|
312
|
-
|
363
|
+
rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
|
364
|
+
rb_global_variable(&rbffi_CallbackInfoClass);
|
313
365
|
|
314
|
-
|
315
|
-
|
316
|
-
rb_define_method(classCallbackInfo, "initialize", cbinfo_initialize, 2);
|
366
|
+
rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
|
367
|
+
rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
|
317
368
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
369
|
+
NativeCallbackClass = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
|
370
|
+
rb_global_variable(&NativeCallbackClass);
|
371
|
+
rb_define_alloc_func(NativeCallbackClass, native_callback_allocate);
|
372
|
+
id_call = rb_intern("call");
|
373
|
+
id_cbtable = rb_intern("@__ffi_callback_table__");
|
322
374
|
}
|
data/ext/ffi_c/Callback.h
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#define _CALLBACK_H
|
3
3
|
|
4
4
|
#include "Types.h"
|
5
|
+
#include "Type.h"
|
5
6
|
|
6
7
|
#ifdef __cplusplus
|
7
8
|
extern "C" {
|
@@ -9,8 +10,12 @@ extern "C" {
|
|
9
10
|
#include <ffi.h>
|
10
11
|
|
11
12
|
typedef struct {
|
12
|
-
|
13
|
-
|
13
|
+
Type type; // The native type of a CallbackInfo object
|
14
|
+
VALUE rbReturnType;
|
15
|
+
VALUE rbParameterTypes;
|
16
|
+
|
17
|
+
Type* returnType;
|
18
|
+
Type** parameterTypes;
|
14
19
|
ffi_type* ffiReturnType;
|
15
20
|
ffi_type** ffiParameterTypes;
|
16
21
|
ffi_cif ffi_cif;
|
@@ -29,9 +34,10 @@ typedef struct {
|
|
29
34
|
VALUE rbProc;
|
30
35
|
} NativeCallback;
|
31
36
|
|
32
|
-
extern VALUE
|
33
|
-
extern
|
34
|
-
extern VALUE
|
37
|
+
extern VALUE rbffi_CallbackInfoClass;
|
38
|
+
extern void rbffi_Callback_Init(VALUE ffiModule);
|
39
|
+
extern VALUE rbffi_NativeCallback_NewInstance(VALUE, VALUE);
|
40
|
+
extern VALUE rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo);
|
35
41
|
|
36
42
|
#ifdef __cplusplus
|
37
43
|
}
|
@@ -12,12 +12,25 @@
|
|
12
12
|
|
13
13
|
#include "rbffi.h"
|
14
14
|
#include "compat.h"
|
15
|
+
#include "AbstractMemory.h"
|
15
16
|
#include "Pointer.h"
|
16
|
-
#include "
|
17
|
+
#include "DynamicLibrary.h"
|
18
|
+
|
19
|
+
typedef struct LibrarySymbol_ {
|
20
|
+
AbstractMemory memory;
|
21
|
+
VALUE library;
|
22
|
+
VALUE name;
|
23
|
+
} LibrarySymbol;
|
17
24
|
|
18
25
|
static VALUE library_initialize(VALUE self, VALUE libname, VALUE libflags);
|
19
26
|
static void library_free(Library* lib);
|
20
|
-
|
27
|
+
|
28
|
+
|
29
|
+
static VALUE symbol_allocate(VALUE klass);
|
30
|
+
static VALUE symbol_new(VALUE library, void* address, VALUE name);
|
31
|
+
static void symbol_mark(LibrarySymbol* sym);
|
32
|
+
|
33
|
+
static VALUE LibraryClass = Qnil, SymbolClass = Qnil;
|
21
34
|
|
22
35
|
#if defined(_WIN32) || defined(__WIN32__)
|
23
36
|
static void* dl_open(const char* name, int flags);
|
@@ -80,7 +93,8 @@ library_dlsym(VALUE self, VALUE name)
|
|
80
93
|
|
81
94
|
Data_Get_Struct(self, Library, library);
|
82
95
|
address = dl_sym(library->handle, StringValueCStr(name));
|
83
|
-
|
96
|
+
|
97
|
+
return address != NULL ? symbol_new(self, address, name) : Qnil;
|
84
98
|
}
|
85
99
|
|
86
100
|
static VALUE
|
@@ -122,21 +136,74 @@ dl_error(char* buf, int size)
|
|
122
136
|
}
|
123
137
|
#endif
|
124
138
|
|
139
|
+
static VALUE
|
140
|
+
symbol_allocate(VALUE klass)
|
141
|
+
{
|
142
|
+
LibrarySymbol* sym;
|
143
|
+
VALUE obj = Data_Make_Struct(klass, LibrarySymbol, NULL, -1, sym);
|
144
|
+
sym->name = Qnil;
|
145
|
+
sym->library = Qnil;
|
146
|
+
|
147
|
+
return obj;
|
148
|
+
}
|
149
|
+
|
150
|
+
static VALUE
|
151
|
+
symbol_new(VALUE library, void* address, VALUE name)
|
152
|
+
{
|
153
|
+
LibrarySymbol* sym;
|
154
|
+
VALUE obj = Data_Make_Struct(SymbolClass, LibrarySymbol, symbol_mark, -1, sym);
|
155
|
+
|
156
|
+
sym->memory.address = address;
|
157
|
+
sym->memory.size = LONG_MAX;
|
158
|
+
sym->library = library;
|
159
|
+
sym->name = name;
|
160
|
+
|
161
|
+
return obj;
|
162
|
+
}
|
163
|
+
|
164
|
+
static void
|
165
|
+
symbol_mark(LibrarySymbol* sym)
|
166
|
+
{
|
167
|
+
rb_gc_mark(sym->library);
|
168
|
+
rb_gc_mark(sym->name);
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE
|
172
|
+
symbol_inspect(VALUE self)
|
173
|
+
{
|
174
|
+
LibrarySymbol* sym;
|
175
|
+
char buf[256];
|
176
|
+
|
177
|
+
Data_Get_Struct(self, LibrarySymbol, sym);
|
178
|
+
snprintf(buf, sizeof(buf), "#<FFI::Library::Symbol name=%s address=%p>",
|
179
|
+
StringValueCStr(sym->name), sym->memory.address);
|
180
|
+
return rb_str_new2(buf);
|
181
|
+
}
|
182
|
+
|
125
183
|
void
|
126
|
-
|
184
|
+
rbffi_DynamicLibrary_Init(VALUE moduleFFI)
|
127
185
|
{
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
186
|
+
LibraryClass = rb_define_class_under(moduleFFI, "DynamicLibrary", rb_cObject);
|
187
|
+
rb_global_variable(&LibraryClass);
|
188
|
+
SymbolClass = rb_define_class_under(LibraryClass, "Symbol", rbffi_PointerClass);
|
189
|
+
rb_global_variable(&SymbolClass);
|
190
|
+
|
191
|
+
rb_define_const(moduleFFI, "NativeLibrary", LibraryClass); // backwards compat library
|
192
|
+
rb_define_alloc_func(LibraryClass, library_allocate);
|
193
|
+
rb_define_singleton_method(LibraryClass, "open", library_open, 2);
|
194
|
+
rb_define_singleton_method(LibraryClass, "last_error", library_dlerror, 0);
|
195
|
+
rb_define_method(LibraryClass, "initialize", library_initialize, 2);
|
196
|
+
rb_define_method(LibraryClass, "find_symbol", library_dlsym, 1);
|
197
|
+
rb_define_method(LibraryClass, "find_function", library_dlsym, 1);
|
198
|
+
rb_define_method(LibraryClass, "find_variable", library_dlsym, 1);
|
199
|
+
rb_define_method(LibraryClass, "last_error", library_dlerror, 0);
|
200
|
+
rb_define_attr(LibraryClass, "name", 1, 0);
|
201
|
+
|
202
|
+
rb_define_alloc_func(SymbolClass, symbol_allocate);
|
203
|
+
rb_undef_method(SymbolClass, "new");
|
204
|
+
rb_define_method(SymbolClass, "inspect", symbol_inspect, 0);
|
205
|
+
|
206
|
+
#define DEF(x) rb_define_const(LibraryClass, "RTLD_" #x, UINT2NUM(RTLD_##x))
|
140
207
|
DEF(LAZY);
|
141
208
|
DEF(NOW);
|
142
209
|
DEF(GLOBAL);
|