ffi 0.4.0-x86-mswin32 → 0.5.0-x86-mswin32
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 +15 -15
- data/Rakefile +57 -8
- data/ext/ffi_c/AbstractMemory.c +101 -24
- data/ext/ffi_c/AbstractMemory.h +98 -6
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +1 -0
- data/ext/ffi_c/Buffer.c +59 -43
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +3 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +30 -6
- data/ext/ffi_c/MemoryPointer.c +50 -28
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Pointer.c +73 -13
- data/ext/ffi_c/Pointer.h +31 -7
- data/ext/ffi_c/Struct.c +517 -224
- data/ext/ffi_c/Struct.h +60 -6
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +121 -22
- data/ext/ffi_c/Type.h +37 -8
- data/ext/ffi_c/Types.c +46 -61
- data/ext/ffi_c/Types.h +38 -7
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +53 -3
- data/ext/ffi_c/extconf.rb +6 -7
- data/ext/ffi_c/ffi.c +45 -39
- data/ext/ffi_c/libffi.darwin.mk +2 -2
- data/ext/ffi_c/rbffi.h +3 -0
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
- data/lib/ffi/ffi.rb +7 -4
- data/lib/ffi/library.rb +34 -59
- data/lib/ffi/platform.rb +14 -4
- data/lib/ffi/struct.rb +110 -281
- data/lib/ffi/union.rb +4 -9
- data/lib/ffi/variadic.rb +1 -6
- data/spec/ffi/buffer_spec.rb +6 -0
- data/spec/ffi/callback_spec.rb +34 -3
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +56 -52
- data/spec/ffi/pointer_spec.rb +3 -3
- data/spec/ffi/struct_callback_spec.rb +26 -3
- data/spec/ffi/struct_spec.rb +56 -3
- metadata +34 -13
- data/ext/ffi_c/Callback.c +0 -374
- data/ext/ffi_c/Callback.h +0 -47
- data/ext/ffi_c/Invoker.c +0 -962
- data/ext/ffi_c/NullPointer.c +0 -143
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: x86-mswin32
|
6
6
|
authors:
|
7
7
|
- Wayne Meissner
|
@@ -9,16 +9,25 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-06 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.8.7
|
24
|
+
version:
|
16
25
|
description: |-
|
17
26
|
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
18
27
|
libraries, binding functions within them, and calling those functions
|
19
28
|
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
20
29
|
on Ruby and JRuby. Discover why should you write your next extension
|
21
|
-
using Ruby-FFI
|
30
|
+
using Ruby-FFI here[http://wiki.github.com/ffi/ffi/why-use-ffi].
|
22
31
|
email: wmeissner@gmail.com
|
23
32
|
executables: []
|
24
33
|
|
@@ -32,17 +41,20 @@ files:
|
|
32
41
|
- README.rdoc
|
33
42
|
- Rakefile
|
34
43
|
- ext/ffi_c/libffi.mk
|
35
|
-
- ext/ffi_c/NullPointer.c
|
36
44
|
- ext/ffi_c/libffi.gnu.mk
|
37
|
-
- ext/ffi_c/
|
38
|
-
- ext/ffi_c/
|
45
|
+
- ext/ffi_c/FunctionInfo.c
|
46
|
+
- ext/ffi_c/StructByValue.h
|
39
47
|
- ext/ffi_c/AbstractMemory.c
|
48
|
+
- ext/ffi_c/ClosurePool.h
|
40
49
|
- ext/ffi_c/MemoryPointer.c
|
41
50
|
- ext/ffi_c/ffi.c
|
42
51
|
- ext/ffi_c/Pointer.c
|
43
52
|
- ext/ffi_c/Platform.c
|
53
|
+
- ext/ffi_c/StructByValue.c
|
54
|
+
- ext/ffi_c/ClosurePool.c
|
44
55
|
- ext/ffi_c/MemoryPointer.h
|
45
56
|
- ext/ffi_c/Type.h
|
57
|
+
- ext/ffi_c/Function.h
|
46
58
|
- ext/ffi_c/libffi/include/Makefile.am
|
47
59
|
- ext/ffi_c/libffi/include/ffi_common.h
|
48
60
|
- ext/ffi_c/libffi/include/ffi.h.in
|
@@ -276,25 +288,33 @@ files:
|
|
276
288
|
- ext/ffi_c/libffi/configure.ac
|
277
289
|
- ext/ffi_c/Platform.h
|
278
290
|
- ext/ffi_c/LastError.c
|
279
|
-
- ext/ffi_c/Callback.h
|
280
291
|
- ext/ffi_c/Struct.c
|
292
|
+
- ext/ffi_c/Function.c
|
281
293
|
- ext/ffi_c/extconf.rb
|
294
|
+
- ext/ffi_c/MethodHandle.c
|
295
|
+
- ext/ffi_c/Call.c
|
282
296
|
- ext/ffi_c/endian.h
|
283
297
|
- ext/ffi_c/Types.c
|
298
|
+
- ext/ffi_c/Variadic.c
|
284
299
|
- ext/ffi_c/DynamicLibrary.h
|
285
300
|
- ext/ffi_c/Struct.h
|
301
|
+
- ext/ffi_c/Call.h
|
286
302
|
- ext/ffi_c/compat.h
|
287
303
|
- ext/ffi_c/Types.h
|
288
304
|
- ext/ffi_c/Pointer.h
|
289
305
|
- ext/ffi_c/Type.c
|
306
|
+
- ext/ffi_c/ArrayType.h
|
290
307
|
- ext/ffi_c/AutoPointer.h
|
291
308
|
- ext/ffi_c/LastError.h
|
309
|
+
- ext/ffi_c/StructLayout.c
|
292
310
|
- ext/ffi_c/AbstractMemory.h
|
311
|
+
- ext/ffi_c/ArrayType.c
|
293
312
|
- ext/ffi_c/libffi.darwin.mk
|
294
313
|
- ext/ffi_c/rbffi.h
|
295
314
|
- ext/ffi_c/DynamicLibrary.c
|
296
315
|
- ext/ffi_c/AutoPointer.c
|
297
316
|
- ext/ffi_c/libffi.bsd.mk
|
317
|
+
- ext/ffi_c/MethodHandle.h
|
298
318
|
- ext/ffi_c/Buffer.c
|
299
319
|
- gen/Rakefile
|
300
320
|
- lib/ffi.rb
|
@@ -336,6 +356,7 @@ files:
|
|
336
356
|
- spec/ffi/buffer_spec.rb
|
337
357
|
- spec/ffi/library_spec.rb
|
338
358
|
- spec/ffi/managed_struct_spec.rb
|
359
|
+
- spec/ffi/function_spec.rb
|
339
360
|
- spec/ffi/variadic_spec.rb
|
340
361
|
- spec/ffi/spec_helper.rb
|
341
362
|
- spec/ffi/pointer_spec.rb
|
@@ -344,7 +365,7 @@ files:
|
|
344
365
|
- lib/1.8/ffi_c.so
|
345
366
|
- lib/1.9/ffi_c.so
|
346
367
|
has_rdoc: true
|
347
|
-
homepage: http://
|
368
|
+
homepage: http://wiki.github.com/ffi/ffi
|
348
369
|
licenses: []
|
349
370
|
|
350
371
|
post_install_message:
|
@@ -354,9 +375,9 @@ require_paths:
|
|
354
375
|
- lib
|
355
376
|
required_ruby_version: !ruby/object:Gem::Requirement
|
356
377
|
requirements:
|
357
|
-
- -
|
378
|
+
- - ">="
|
358
379
|
- !ruby/object:Gem::Version
|
359
|
-
version:
|
380
|
+
version: "0"
|
360
381
|
version:
|
361
382
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
362
383
|
requirements:
|
@@ -367,7 +388,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
367
388
|
requirements: []
|
368
389
|
|
369
390
|
rubyforge_project: ffi
|
370
|
-
rubygems_version: 1.3.
|
391
|
+
rubygems_version: 1.3.5
|
371
392
|
signing_key:
|
372
393
|
specification_version: 3
|
373
394
|
summary: Ruby-FFI is a ruby extension for programmatically loading dynamic libraries, binding functions within them, and calling those functions from Ruby code
|
data/ext/ffi_c/Callback.c
DELETED
@@ -1,374 +0,0 @@
|
|
1
|
-
#include <sys/param.h>
|
2
|
-
#include <sys/types.h>
|
3
|
-
#ifndef _WIN32
|
4
|
-
# include <sys/mman.h>
|
5
|
-
#endif
|
6
|
-
#include <ruby.h>
|
7
|
-
#include <ffi.h>
|
8
|
-
#include "AbstractMemory.h"
|
9
|
-
#include "Pointer.h"
|
10
|
-
#include "MemoryPointer.h"
|
11
|
-
#include "Callback.h"
|
12
|
-
#include "Types.h"
|
13
|
-
#include "Type.h"
|
14
|
-
#include "rbffi.h"
|
15
|
-
#include "compat.h"
|
16
|
-
#include "extconf.h"
|
17
|
-
|
18
|
-
static void cbinfo_mark(CallbackInfo* cbInfo);
|
19
|
-
static void cbinfo_free(CallbackInfo *);
|
20
|
-
|
21
|
-
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
22
|
-
static void* ffi_closure_alloc(size_t size, void** code);
|
23
|
-
static void ffi_closure_free(void* ptr);
|
24
|
-
ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
25
|
-
void (*fun)(ffi_cif*, void*, void**, void*),
|
26
|
-
void* user_data, void* code);
|
27
|
-
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
28
|
-
|
29
|
-
static VALUE CallbackInfoClass = Qnil;
|
30
|
-
static VALUE NativeCallbackClass = Qnil;
|
31
|
-
static ID id_call = Qnil, id_cbtable = Qnil;
|
32
|
-
|
33
|
-
VALUE rbffi_CallbackInfoClass = Qnil;
|
34
|
-
|
35
|
-
static VALUE
|
36
|
-
cbinfo_allocate(VALUE klass)
|
37
|
-
{
|
38
|
-
CallbackInfo* cbInfo;
|
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;
|
48
|
-
}
|
49
|
-
|
50
|
-
static VALUE
|
51
|
-
cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
|
52
|
-
{
|
53
|
-
CallbackInfo *cbInfo;
|
54
|
-
int paramCount;
|
55
|
-
ffi_status status;
|
56
|
-
int i;
|
57
|
-
|
58
|
-
Check_Type(rbParamTypes, T_ARRAY);
|
59
|
-
|
60
|
-
|
61
|
-
paramCount = RARRAY_LEN(rbParamTypes);
|
62
|
-
|
63
|
-
Data_Get_Struct(self, CallbackInfo, cbInfo);
|
64
|
-
cbInfo->parameterCount = paramCount;
|
65
|
-
cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
|
66
|
-
cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
|
67
|
-
Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
|
68
|
-
cbInfo->rbReturnType = rbReturnType;
|
69
|
-
cbInfo->rbParameterTypes = rbParamTypes;
|
70
|
-
|
71
|
-
for (i = 0; i < paramCount; ++i) {
|
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;
|
78
|
-
if (cbInfo->ffiParameterTypes[i] == NULL) {
|
79
|
-
rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
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;
|
88
|
-
if (cbInfo->ffiReturnType == NULL) {
|
89
|
-
rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
|
90
|
-
}
|
91
|
-
#if defined(_WIN32) && defined(notyet)
|
92
|
-
cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
93
|
-
#else
|
94
|
-
cbInfo->abi = FFI_DEFAULT_ABI;
|
95
|
-
#endif
|
96
|
-
status = ffi_prep_cif(&cbInfo->ffi_cif, cbInfo->abi, cbInfo->parameterCount,
|
97
|
-
cbInfo->ffiReturnType, cbInfo->ffiParameterTypes);
|
98
|
-
switch (status) {
|
99
|
-
case FFI_BAD_ABI:
|
100
|
-
rb_raise(rb_eArgError, "Invalid ABI specified");
|
101
|
-
case FFI_BAD_TYPEDEF:
|
102
|
-
rb_raise(rb_eArgError, "Invalid argument type specified");
|
103
|
-
case FFI_OK:
|
104
|
-
break;
|
105
|
-
default:
|
106
|
-
rb_raise(rb_eArgError, "Unknown FFI error");
|
107
|
-
}
|
108
|
-
return self;
|
109
|
-
}
|
110
|
-
|
111
|
-
static void
|
112
|
-
cbinfo_mark(CallbackInfo* cbInfo)
|
113
|
-
{
|
114
|
-
rb_gc_mark(cbInfo->rbReturnType);
|
115
|
-
rb_gc_mark(cbInfo->rbParameterTypes);
|
116
|
-
}
|
117
|
-
|
118
|
-
static void
|
119
|
-
cbinfo_free(CallbackInfo* cbInfo)
|
120
|
-
{
|
121
|
-
if (cbInfo->parameterTypes != NULL) {
|
122
|
-
xfree(cbInfo->parameterTypes);
|
123
|
-
}
|
124
|
-
if (cbInfo->ffiParameterTypes != NULL) {
|
125
|
-
xfree(cbInfo->ffiParameterTypes);
|
126
|
-
}
|
127
|
-
xfree(cbInfo);
|
128
|
-
}
|
129
|
-
|
130
|
-
static void
|
131
|
-
native_callback_free(NativeCallback* cb)
|
132
|
-
{
|
133
|
-
if (cb->ffi_closure != NULL) {
|
134
|
-
ffi_closure_free(cb->ffi_closure);
|
135
|
-
}
|
136
|
-
xfree(cb);
|
137
|
-
}
|
138
|
-
|
139
|
-
static void
|
140
|
-
native_callback_mark(NativeCallback* cb)
|
141
|
-
{
|
142
|
-
rb_gc_mark(cb->rbCallbackInfo);
|
143
|
-
rb_gc_mark(cb->rbProc);
|
144
|
-
}
|
145
|
-
|
146
|
-
static void
|
147
|
-
native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
148
|
-
{
|
149
|
-
NativeCallback* cb = (NativeCallback *) user_data;
|
150
|
-
CallbackInfo *cbInfo = cb->cbInfo;
|
151
|
-
VALUE* rbParams;
|
152
|
-
VALUE rbReturnValue;
|
153
|
-
int i;
|
154
|
-
|
155
|
-
rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
|
156
|
-
for (i = 0; i < cbInfo->parameterCount; ++i) {
|
157
|
-
VALUE param;
|
158
|
-
switch (cbInfo->parameterTypes[i]->nativeType) {
|
159
|
-
case NATIVE_INT8:
|
160
|
-
param = INT2NUM(*(int8_t *) parameters[i]);
|
161
|
-
break;
|
162
|
-
case NATIVE_UINT8:
|
163
|
-
param = UINT2NUM(*(uint8_t *) parameters[i]);
|
164
|
-
break;
|
165
|
-
case NATIVE_INT16:
|
166
|
-
param = INT2NUM(*(int16_t *) parameters[i]);
|
167
|
-
break;
|
168
|
-
case NATIVE_UINT16:
|
169
|
-
param = UINT2NUM(*(uint16_t *) parameters[i]);
|
170
|
-
break;
|
171
|
-
case NATIVE_INT32:
|
172
|
-
param = INT2NUM(*(int32_t *) parameters[i]);
|
173
|
-
break;
|
174
|
-
case NATIVE_UINT32:
|
175
|
-
param = UINT2NUM(*(uint32_t *) parameters[i]);
|
176
|
-
break;
|
177
|
-
case NATIVE_INT64:
|
178
|
-
param = LL2NUM(*(int64_t *) parameters[i]);
|
179
|
-
break;
|
180
|
-
case NATIVE_UINT64:
|
181
|
-
param = ULL2NUM(*(uint64_t *) parameters[i]);
|
182
|
-
break;
|
183
|
-
case NATIVE_FLOAT32:
|
184
|
-
param = rb_float_new(*(float *) parameters[i]);
|
185
|
-
break;
|
186
|
-
case NATIVE_FLOAT64:
|
187
|
-
param = rb_float_new(*(double *) parameters[i]);
|
188
|
-
break;
|
189
|
-
case NATIVE_STRING:
|
190
|
-
param = rb_tainted_str_new2(*(char **) parameters[i]);
|
191
|
-
break;
|
192
|
-
case NATIVE_POINTER:
|
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);
|
201
|
-
break;
|
202
|
-
default:
|
203
|
-
param = Qnil;
|
204
|
-
break;
|
205
|
-
}
|
206
|
-
rbParams[i] = param;
|
207
|
-
}
|
208
|
-
rbReturnValue = rb_funcall2(cb->rbProc, id_call, cbInfo->parameterCount, rbParams);
|
209
|
-
if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
|
210
|
-
memset(retval, 0, cbInfo->ffiReturnType->size);
|
211
|
-
} else switch (cbInfo->returnType->nativeType) {
|
212
|
-
case NATIVE_INT8:
|
213
|
-
case NATIVE_INT16:
|
214
|
-
case NATIVE_INT32:
|
215
|
-
*((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
|
216
|
-
break;
|
217
|
-
case NATIVE_UINT8:
|
218
|
-
case NATIVE_UINT16:
|
219
|
-
case NATIVE_UINT32:
|
220
|
-
*((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
|
221
|
-
break;
|
222
|
-
case NATIVE_INT64:
|
223
|
-
*((int64_t *) retval) = NUM2LL(rbReturnValue);
|
224
|
-
break;
|
225
|
-
case NATIVE_UINT64:
|
226
|
-
*((uint64_t *) retval) = NUM2ULL(rbReturnValue);
|
227
|
-
break;
|
228
|
-
case NATIVE_FLOAT32:
|
229
|
-
*((float *) retval) = (float) NUM2DBL(rbReturnValue);
|
230
|
-
break;
|
231
|
-
case NATIVE_FLOAT64:
|
232
|
-
*((double *) retval) = NUM2DBL(rbReturnValue);
|
233
|
-
break;
|
234
|
-
case NATIVE_POINTER:
|
235
|
-
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
|
236
|
-
*((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
|
237
|
-
} else {
|
238
|
-
// Default to returning NULL if not a value pointer object. handles nil case as well
|
239
|
-
*((void **) retval) = NULL;
|
240
|
-
}
|
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
|
-
|
257
|
-
default:
|
258
|
-
*((ffi_arg *) retval) = 0;
|
259
|
-
break;
|
260
|
-
}
|
261
|
-
}
|
262
|
-
|
263
|
-
static VALUE
|
264
|
-
native_callback_allocate(VALUE klass)
|
265
|
-
{
|
266
|
-
NativeCallback* closure;
|
267
|
-
VALUE obj;
|
268
|
-
|
269
|
-
obj = Data_Make_Struct(klass, NativeCallback, native_callback_mark, native_callback_free, closure);
|
270
|
-
closure->rbCallbackInfo = Qnil;
|
271
|
-
closure->rbProc = Qnil;
|
272
|
-
|
273
|
-
return obj;
|
274
|
-
}
|
275
|
-
|
276
|
-
VALUE
|
277
|
-
rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
|
278
|
-
{
|
279
|
-
NativeCallback* closure = NULL;
|
280
|
-
CallbackInfo* cbInfo;
|
281
|
-
VALUE obj;
|
282
|
-
ffi_status status;
|
283
|
-
|
284
|
-
Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
|
285
|
-
obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
|
286
|
-
closure->cbInfo = cbInfo;
|
287
|
-
closure->rbProc = rbProc;
|
288
|
-
closure->rbCallbackInfo = rbCallbackInfo;
|
289
|
-
|
290
|
-
closure->ffi_closure = ffi_closure_alloc(sizeof(*closure->ffi_closure), &closure->code);
|
291
|
-
if (closure->ffi_closure == NULL) {
|
292
|
-
rb_raise(rb_eNoMemError, "Failed to allocate FFI native closure");
|
293
|
-
}
|
294
|
-
|
295
|
-
status = ffi_prep_closure_loc(closure->ffi_closure, &cbInfo->ffi_cif,
|
296
|
-
native_callback_invoke, closure, closure->code);
|
297
|
-
if (status != FFI_OK) {
|
298
|
-
rb_raise(rb_eArgError, "ffi_prep_closure_loc failed");
|
299
|
-
}
|
300
|
-
|
301
|
-
return obj;
|
302
|
-
}
|
303
|
-
|
304
|
-
VALUE
|
305
|
-
rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
|
306
|
-
{
|
307
|
-
VALUE callback;
|
308
|
-
VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
|
309
|
-
if (cbTable == Qnil) {
|
310
|
-
cbTable = rb_hash_new();
|
311
|
-
rb_ivar_set(proc, id_cbtable, cbTable);
|
312
|
-
}
|
313
|
-
callback = rb_hash_aref(cbTable, cbInfo);
|
314
|
-
if (callback != Qnil) {
|
315
|
-
return callback;
|
316
|
-
}
|
317
|
-
callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
|
318
|
-
rb_hash_aset(cbTable, cbInfo, callback);
|
319
|
-
return callback;
|
320
|
-
}
|
321
|
-
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
322
|
-
/*
|
323
|
-
* versions of ffi_closure_alloc, ffi_closure_free and ffi_prep_closure_loc for older
|
324
|
-
* system libffi versions.
|
325
|
-
*/
|
326
|
-
static void*
|
327
|
-
ffi_closure_alloc(size_t size, void** code)
|
328
|
-
{
|
329
|
-
void* closure;
|
330
|
-
closure = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
331
|
-
MAP_ANON | MAP_PRIVATE, -1, 0);
|
332
|
-
if (closure == (void *) -1) {
|
333
|
-
return NULL;
|
334
|
-
}
|
335
|
-
memset(closure, 0, size);
|
336
|
-
*code = closure;
|
337
|
-
return closure;
|
338
|
-
}
|
339
|
-
|
340
|
-
static void
|
341
|
-
ffi_closure_free(void* ptr)
|
342
|
-
{
|
343
|
-
munmap(ptr, sizeof(ffi_closure));
|
344
|
-
}
|
345
|
-
|
346
|
-
ffi_status
|
347
|
-
ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
348
|
-
void (*fun)(ffi_cif*, void*, void**, void*),
|
349
|
-
void* user_data, void* code)
|
350
|
-
{
|
351
|
-
ffi_status retval = ffi_prep_closure(closure, cif, fun, user_data);
|
352
|
-
if (retval == FFI_OK) {
|
353
|
-
mprotect(closure, sizeof(ffi_closure), PROT_READ | PROT_EXEC);
|
354
|
-
}
|
355
|
-
return retval;
|
356
|
-
}
|
357
|
-
|
358
|
-
#endif /* HAVE_FFI_CLOSURE_ALLOC */
|
359
|
-
|
360
|
-
void
|
361
|
-
rbffi_Callback_Init(VALUE moduleFFI)
|
362
|
-
{
|
363
|
-
rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
|
364
|
-
rb_global_variable(&rbffi_CallbackInfoClass);
|
365
|
-
|
366
|
-
rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
|
367
|
-
rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
|
368
|
-
|
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__");
|
374
|
-
}
|