ffi 0.4.0 → 0.5.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 +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/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 +42 -11
- 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: ruby
|
6
6
|
authors:
|
7
7
|
- Wayne Meissner
|
@@ -9,16 +9,35 @@ 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:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bones
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.5.1
|
34
|
+
version:
|
16
35
|
description: |-
|
17
36
|
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
18
37
|
libraries, binding functions within them, and calling those functions
|
19
38
|
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
20
39
|
on Ruby and JRuby. Discover why should you write your next extension
|
21
|
-
using Ruby-FFI
|
40
|
+
using Ruby-FFI here[http://wiki.github.com/ffi/ffi/why-use-ffi].
|
22
41
|
email: wmeissner@gmail.com
|
23
42
|
executables: []
|
24
43
|
|
@@ -33,29 +52,40 @@ files:
|
|
33
52
|
- Rakefile
|
34
53
|
- ext/ffi_c/AbstractMemory.c
|
35
54
|
- ext/ffi_c/AbstractMemory.h
|
55
|
+
- ext/ffi_c/ArrayType.c
|
56
|
+
- ext/ffi_c/ArrayType.h
|
36
57
|
- ext/ffi_c/AutoPointer.c
|
37
58
|
- ext/ffi_c/AutoPointer.h
|
38
59
|
- ext/ffi_c/Buffer.c
|
39
|
-
- ext/ffi_c/
|
40
|
-
- ext/ffi_c/
|
60
|
+
- ext/ffi_c/Call.c
|
61
|
+
- ext/ffi_c/Call.h
|
62
|
+
- ext/ffi_c/ClosurePool.c
|
63
|
+
- ext/ffi_c/ClosurePool.h
|
41
64
|
- ext/ffi_c/DynamicLibrary.c
|
42
65
|
- ext/ffi_c/DynamicLibrary.h
|
43
|
-
- ext/ffi_c/
|
66
|
+
- ext/ffi_c/Function.c
|
67
|
+
- ext/ffi_c/Function.h
|
68
|
+
- ext/ffi_c/FunctionInfo.c
|
44
69
|
- ext/ffi_c/LastError.c
|
45
70
|
- ext/ffi_c/LastError.h
|
46
71
|
- ext/ffi_c/MemoryPointer.c
|
47
72
|
- ext/ffi_c/MemoryPointer.h
|
48
|
-
- ext/ffi_c/
|
73
|
+
- ext/ffi_c/MethodHandle.c
|
74
|
+
- ext/ffi_c/MethodHandle.h
|
49
75
|
- ext/ffi_c/Platform.c
|
50
76
|
- ext/ffi_c/Platform.h
|
51
77
|
- ext/ffi_c/Pointer.c
|
52
78
|
- ext/ffi_c/Pointer.h
|
53
79
|
- ext/ffi_c/Struct.c
|
54
80
|
- ext/ffi_c/Struct.h
|
81
|
+
- ext/ffi_c/StructByValue.c
|
82
|
+
- ext/ffi_c/StructByValue.h
|
83
|
+
- ext/ffi_c/StructLayout.c
|
55
84
|
- ext/ffi_c/Type.c
|
56
85
|
- ext/ffi_c/Type.h
|
57
86
|
- ext/ffi_c/Types.c
|
58
87
|
- ext/ffi_c/Types.h
|
88
|
+
- ext/ffi_c/Variadic.c
|
59
89
|
- ext/ffi_c/compat.h
|
60
90
|
- ext/ffi_c/endian.h
|
61
91
|
- ext/ffi_c/extconf.rb
|
@@ -324,6 +354,7 @@ files:
|
|
324
354
|
- spec/ffi/callback_spec.rb
|
325
355
|
- spec/ffi/enum_spec.rb
|
326
356
|
- spec/ffi/errno_spec.rb
|
357
|
+
- spec/ffi/function_spec.rb
|
327
358
|
- spec/ffi/library_spec.rb
|
328
359
|
- spec/ffi/managed_struct_spec.rb
|
329
360
|
- spec/ffi/number_spec.rb
|
@@ -342,7 +373,7 @@ files:
|
|
342
373
|
- spec/ffi/variadic_spec.rb
|
343
374
|
- spec/spec.opts
|
344
375
|
has_rdoc: true
|
345
|
-
homepage: http://
|
376
|
+
homepage: http://wiki.github.com/ffi/ffi
|
346
377
|
licenses: []
|
347
378
|
|
348
379
|
post_install_message:
|
@@ -369,7 +400,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
369
400
|
requirements: []
|
370
401
|
|
371
402
|
rubyforge_project: ffi
|
372
|
-
rubygems_version: 1.3.
|
403
|
+
rubygems_version: 1.3.5
|
373
404
|
signing_key:
|
374
405
|
specification_version: 3
|
375
406
|
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
|
-
}
|