fiddle 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -1
- data/Rakefile +3 -5
- data/bin/downloader.rb +331 -0
- data/bin/extlibs.rb +262 -0
- data/ext/fiddle/closure.c +5 -4
- data/ext/fiddle/conversions.c +161 -16
- data/ext/fiddle/conversions.h +14 -4
- data/ext/fiddle/depend +83 -0
- data/ext/fiddle/extconf.rb +54 -28
- data/ext/fiddle/extlibs +10 -2
- data/ext/fiddle/fiddle.c +46 -35
- data/ext/fiddle/fiddle.h +35 -1
- data/ext/fiddle/function.c +220 -81
- data/ext/fiddle/handle.c +10 -12
- data/ext/fiddle/pinned.c +123 -0
- data/ext/fiddle/pointer.c +106 -24
- data/ext/fiddle/win32/fficonfig.h +0 -0
- data/ext/fiddle/win32/libffi-config.rb +1 -1
- data/ext/fiddle/win32/libffi.mk.tmpl +0 -0
- data/fiddle.gemspec +46 -4
- data/lib/fiddle.rb +3 -1
- data/lib/fiddle/cparser.rb +29 -2
- data/lib/fiddle/import.rb +11 -9
- data/lib/fiddle/pack.rb +14 -7
- data/lib/fiddle/struct.rb +267 -43
- data/lib/fiddle/value.rb +18 -9
- data/lib/fiddle/version.rb +3 -0
- metadata +13 -12
- data/.gitignore +0 -13
- data/.travis.yml +0 -7
- data/Gemfile +0 -4
- data/bin/console +0 -14
- data/bin/setup +0 -8
data/ext/fiddle/extlibs
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
|
1
|
+
ver = 3.2.1
|
2
|
+
pkg = libffi-$(ver)
|
3
|
+
|
4
|
+
https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/$(pkg).tar.gz \
|
2
5
|
md5:83b89587607e3eb65c70d361f13bab43 \
|
3
6
|
sha512:980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483 \
|
4
7
|
#
|
5
|
-
win32
|
8
|
+
win32/$(pkg)-mswin.patch -p0
|
9
|
+
|
10
|
+
$(pkg)/config.guess -> /tool/config.guess
|
11
|
+
$(pkg)/config.sub -> /tool/config.sub
|
12
|
+
|
13
|
+
! chdir: $(pkg)| autoconf || exit 0
|
data/ext/fiddle/fiddle.c
CHANGED
@@ -1,41 +1,11 @@
|
|
1
1
|
#include <fiddle.h>
|
2
2
|
|
3
3
|
VALUE mFiddle;
|
4
|
+
VALUE rb_eFiddleDLError;
|
4
5
|
VALUE rb_eFiddleError;
|
5
6
|
|
6
|
-
#ifndef TYPE_SSIZE_T
|
7
|
-
# if SIZEOF_SIZE_T == SIZEOF_INT
|
8
|
-
# define TYPE_SSIZE_T TYPE_INT
|
9
|
-
# elif SIZEOF_SIZE_T == SIZEOF_LONG
|
10
|
-
# define TYPE_SSIZE_T TYPE_LONG
|
11
|
-
# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
|
12
|
-
# define TYPE_SSIZE_T TYPE_LONG_LONG
|
13
|
-
# endif
|
14
|
-
#endif
|
15
|
-
#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
|
16
|
-
|
17
|
-
#ifndef TYPE_PTRDIFF_T
|
18
|
-
# if SIZEOF_PTRDIFF_T == SIZEOF_INT
|
19
|
-
# define TYPE_PTRDIFF_T TYPE_INT
|
20
|
-
# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
|
21
|
-
# define TYPE_PTRDIFF_T TYPE_LONG
|
22
|
-
# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
|
23
|
-
# define TYPE_PTRDIFF_T TYPE_LONG_LONG
|
24
|
-
# endif
|
25
|
-
#endif
|
26
|
-
|
27
|
-
#ifndef TYPE_INTPTR_T
|
28
|
-
# if SIZEOF_INTPTR_T == SIZEOF_INT
|
29
|
-
# define TYPE_INTPTR_T TYPE_INT
|
30
|
-
# elif SIZEOF_INTPTR_T == SIZEOF_LONG
|
31
|
-
# define TYPE_INTPTR_T TYPE_LONG
|
32
|
-
# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
|
33
|
-
# define TYPE_INTPTR_T TYPE_LONG_LONG
|
34
|
-
# endif
|
35
|
-
#endif
|
36
|
-
#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
|
37
|
-
|
38
7
|
void Init_fiddle_pointer(void);
|
8
|
+
void Init_fiddle_pinned(void);
|
39
9
|
|
40
10
|
/*
|
41
11
|
* call-seq: Fiddle.malloc(size)
|
@@ -47,8 +17,7 @@ static VALUE
|
|
47
17
|
rb_fiddle_malloc(VALUE self, VALUE size)
|
48
18
|
{
|
49
19
|
void *ptr;
|
50
|
-
|
51
|
-
ptr = (void*)ruby_xmalloc(NUM2SIZET(size));
|
20
|
+
ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
|
52
21
|
return PTR2NUM(ptr);
|
53
22
|
}
|
54
23
|
|
@@ -163,12 +132,33 @@ Init_fiddle(void)
|
|
163
132
|
*/
|
164
133
|
mFiddle = rb_define_module("Fiddle");
|
165
134
|
|
135
|
+
/*
|
136
|
+
* Document-class: Fiddle::Error
|
137
|
+
*
|
138
|
+
* Generic error class for Fiddle
|
139
|
+
*/
|
140
|
+
rb_eFiddleError = rb_define_class_under(mFiddle, "Error", rb_eStandardError);
|
141
|
+
|
142
|
+
/*
|
143
|
+
* Ruby installed by RubyInstaller for Windows always require
|
144
|
+
* bundled Fiddle because ruby_installer/runtime/dll_directory.rb
|
145
|
+
* requires Fiddle. It's used by
|
146
|
+
* rubygems/defaults/operating_system.rb. It means that the
|
147
|
+
* bundled Fiddle is always required on initialization.
|
148
|
+
*
|
149
|
+
* We just remove existing Fiddle::DLError here to override
|
150
|
+
* the bundled Fiddle.
|
151
|
+
*/
|
152
|
+
if (rb_const_defined(mFiddle, rb_intern("DLError"))) {
|
153
|
+
rb_const_remove(mFiddle, rb_intern("DLError"));
|
154
|
+
}
|
155
|
+
|
166
156
|
/*
|
167
157
|
* Document-class: Fiddle::DLError
|
168
158
|
*
|
169
159
|
* standard dynamic load exception
|
170
160
|
*/
|
171
|
-
|
161
|
+
rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError);
|
172
162
|
|
173
163
|
/* Document-const: TYPE_VOID
|
174
164
|
*
|
@@ -226,6 +216,20 @@ Init_fiddle(void)
|
|
226
216
|
*/
|
227
217
|
rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
|
228
218
|
|
219
|
+
#ifdef HAVE_FFI_PREP_CIF_VAR
|
220
|
+
/* Document-const: TYPE_VARIADIC
|
221
|
+
*
|
222
|
+
* C type - ...
|
223
|
+
*/
|
224
|
+
rb_define_const(mFiddle, "TYPE_VARIADIC", INT2NUM(TYPE_VARIADIC));
|
225
|
+
#endif
|
226
|
+
|
227
|
+
/* Document-const: TYPE_CONST_STRING
|
228
|
+
*
|
229
|
+
* C type - const char* ('\0' terminated const char*)
|
230
|
+
*/
|
231
|
+
rb_define_const(mFiddle, "TYPE_CONST_STRING", INT2NUM(TYPE_CONST_STRING));
|
232
|
+
|
229
233
|
/* Document-const: TYPE_SIZE_T
|
230
234
|
*
|
231
235
|
* C type - size_t
|
@@ -426,6 +430,12 @@ Init_fiddle(void)
|
|
426
430
|
*/
|
427
431
|
rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
|
428
432
|
|
433
|
+
/* Document-const: SIZEOF_CONST_STRING
|
434
|
+
*
|
435
|
+
* size of a const char*
|
436
|
+
*/
|
437
|
+
rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*)));
|
438
|
+
|
429
439
|
/* Document-const: RUBY_FREE
|
430
440
|
*
|
431
441
|
* Address of the ruby_xfree() function
|
@@ -450,5 +460,6 @@ Init_fiddle(void)
|
|
450
460
|
Init_fiddle_closure();
|
451
461
|
Init_fiddle_handle();
|
452
462
|
Init_fiddle_pointer();
|
463
|
+
Init_fiddle_pinned();
|
453
464
|
}
|
454
465
|
/* vim: set noet sws=4 sw=4: */
|
data/ext/fiddle/fiddle.h
CHANGED
@@ -115,6 +115,40 @@
|
|
115
115
|
#endif
|
116
116
|
#define TYPE_FLOAT 7
|
117
117
|
#define TYPE_DOUBLE 8
|
118
|
+
#define TYPE_VARIADIC 9
|
119
|
+
#define TYPE_CONST_STRING 10
|
120
|
+
|
121
|
+
#ifndef TYPE_SSIZE_T
|
122
|
+
# if SIZEOF_SIZE_T == SIZEOF_INT
|
123
|
+
# define TYPE_SSIZE_T TYPE_INT
|
124
|
+
# elif SIZEOF_SIZE_T == SIZEOF_LONG
|
125
|
+
# define TYPE_SSIZE_T TYPE_LONG
|
126
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
|
127
|
+
# define TYPE_SSIZE_T TYPE_LONG_LONG
|
128
|
+
# endif
|
129
|
+
#endif
|
130
|
+
#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
|
131
|
+
|
132
|
+
#ifndef TYPE_PTRDIFF_T
|
133
|
+
# if SIZEOF_PTRDIFF_T == SIZEOF_INT
|
134
|
+
# define TYPE_PTRDIFF_T TYPE_INT
|
135
|
+
# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
|
136
|
+
# define TYPE_PTRDIFF_T TYPE_LONG
|
137
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
|
138
|
+
# define TYPE_PTRDIFF_T TYPE_LONG_LONG
|
139
|
+
# endif
|
140
|
+
#endif
|
141
|
+
|
142
|
+
#ifndef TYPE_INTPTR_T
|
143
|
+
# if SIZEOF_INTPTR_T == SIZEOF_INT
|
144
|
+
# define TYPE_INTPTR_T TYPE_INT
|
145
|
+
# elif SIZEOF_INTPTR_T == SIZEOF_LONG
|
146
|
+
# define TYPE_INTPTR_T TYPE_LONG
|
147
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
|
148
|
+
# define TYPE_INTPTR_T TYPE_LONG_LONG
|
149
|
+
# endif
|
150
|
+
#endif
|
151
|
+
#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
|
118
152
|
|
119
153
|
#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
|
120
154
|
|
@@ -130,7 +164,7 @@
|
|
130
164
|
#define ALIGN_DOUBLE ALIGN_OF(double)
|
131
165
|
|
132
166
|
extern VALUE mFiddle;
|
133
|
-
extern VALUE
|
167
|
+
extern VALUE rb_eFiddleDLError;
|
134
168
|
|
135
169
|
VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
|
136
170
|
|
data/ext/fiddle/function.c
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#include <fiddle.h>
|
2
2
|
#include <ruby/thread.h>
|
3
3
|
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
4
6
|
#ifdef PRIsVALUE
|
5
7
|
# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
|
6
8
|
# define RB_OBJ_STRING(obj) (obj)
|
@@ -19,21 +21,21 @@ VALUE cFiddleFunction;
|
|
19
21
|
#define Check_Max_Args_Long(name, len) \
|
20
22
|
Check_Max_Args_(name, len, "l")
|
21
23
|
#define Check_Max_Args_(name, len, fmt) \
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
}
|
24
|
+
do { \
|
25
|
+
if ((size_t)(len) >= MAX_ARGS) { \
|
26
|
+
rb_raise(rb_eTypeError, \
|
27
|
+
"%s is so large " \
|
28
|
+
"that it can cause integer overflow (%"fmt"d)", \
|
29
|
+
(name), (len)); \
|
30
|
+
} \
|
31
|
+
} while (0)
|
30
32
|
|
31
33
|
static void
|
32
34
|
deallocate(void *p)
|
33
35
|
{
|
34
|
-
ffi_cif *
|
35
|
-
if (
|
36
|
-
xfree(
|
36
|
+
ffi_cif *cif = p;
|
37
|
+
if (cif->arg_types) xfree(cif->arg_types);
|
38
|
+
xfree(cif);
|
37
39
|
}
|
38
40
|
|
39
41
|
static size_t
|
@@ -87,60 +89,91 @@ parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
|
|
87
89
|
return ST_CONTINUE;
|
88
90
|
}
|
89
91
|
|
92
|
+
static VALUE
|
93
|
+
normalize_argument_types(const char *name,
|
94
|
+
VALUE arg_types,
|
95
|
+
bool *is_variadic)
|
96
|
+
{
|
97
|
+
VALUE normalized_arg_types;
|
98
|
+
int i;
|
99
|
+
int n_arg_types;
|
100
|
+
*is_variadic = false;
|
101
|
+
|
102
|
+
Check_Type(arg_types, T_ARRAY);
|
103
|
+
n_arg_types = RARRAY_LENINT(arg_types);
|
104
|
+
Check_Max_Args(name, n_arg_types);
|
105
|
+
|
106
|
+
normalized_arg_types = rb_ary_new_capa(n_arg_types);
|
107
|
+
for (i = 0; i < n_arg_types; i++) {
|
108
|
+
VALUE arg_type = RARRAY_AREF(arg_types, i);
|
109
|
+
int c_arg_type;
|
110
|
+
arg_type = rb_fiddle_type_ensure(arg_type);
|
111
|
+
c_arg_type = NUM2INT(arg_type);
|
112
|
+
if (c_arg_type == TYPE_VARIADIC) {
|
113
|
+
if (i != n_arg_types - 1) {
|
114
|
+
rb_raise(rb_eArgError,
|
115
|
+
"Fiddle::TYPE_VARIADIC must be the last argument type: "
|
116
|
+
"%"PRIsVALUE,
|
117
|
+
arg_types);
|
118
|
+
}
|
119
|
+
*is_variadic = true;
|
120
|
+
break;
|
121
|
+
}
|
122
|
+
else {
|
123
|
+
(void)INT2FFI_TYPE(c_arg_type); /* raise */
|
124
|
+
}
|
125
|
+
rb_ary_push(normalized_arg_types, INT2FIX(c_arg_type));
|
126
|
+
}
|
127
|
+
|
128
|
+
/* freeze to prevent inconsistency at calling #to_int later */
|
129
|
+
OBJ_FREEZE(normalized_arg_types);
|
130
|
+
return normalized_arg_types;
|
131
|
+
}
|
132
|
+
|
90
133
|
static VALUE
|
91
134
|
initialize(int argc, VALUE argv[], VALUE self)
|
92
135
|
{
|
93
136
|
ffi_cif * cif;
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
int nabi;
|
137
|
+
VALUE ptr, arg_types, ret_type, abi, kwds;
|
138
|
+
int c_ret_type;
|
139
|
+
bool is_variadic = false;
|
140
|
+
ffi_abi c_ffi_abi;
|
99
141
|
void *cfunc;
|
100
142
|
|
101
|
-
rb_scan_args(argc, argv, "31:", &ptr, &
|
143
|
+
rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwds);
|
144
|
+
rb_iv_set(self, "@closure", ptr);
|
145
|
+
|
102
146
|
ptr = rb_Integer(ptr);
|
103
147
|
cfunc = NUM2PTR(ptr);
|
104
148
|
PTR2NUM(cfunc);
|
105
|
-
|
106
|
-
abi = INT2FIX(
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
149
|
+
c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
|
150
|
+
abi = INT2FIX(c_ffi_abi);
|
151
|
+
ret_type = rb_fiddle_type_ensure(ret_type);
|
152
|
+
c_ret_type = NUM2INT(ret_type);
|
153
|
+
(void)INT2FFI_TYPE(c_ret_type); /* raise */
|
154
|
+
ret_type = INT2FIX(c_ret_type);
|
155
|
+
|
156
|
+
arg_types = normalize_argument_types("argument types",
|
157
|
+
arg_types,
|
158
|
+
&is_variadic);
|
159
|
+
#ifndef HAVE_FFI_PREP_CIF_VAR
|
160
|
+
if (is_variadic) {
|
161
|
+
rb_raise(rb_eNotImpError,
|
162
|
+
"ffi_prep_cif_var() is required in libffi "
|
163
|
+
"for variadic arguments");
|
120
164
|
}
|
121
|
-
|
165
|
+
#endif
|
122
166
|
|
123
167
|
rb_iv_set(self, "@ptr", ptr);
|
124
|
-
rb_iv_set(self, "@
|
168
|
+
rb_iv_set(self, "@argument_types", arg_types);
|
125
169
|
rb_iv_set(self, "@return_type", ret_type);
|
126
170
|
rb_iv_set(self, "@abi", abi);
|
171
|
+
rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse);
|
127
172
|
|
128
173
|
if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
|
129
174
|
|
130
175
|
TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
|
131
|
-
|
132
|
-
arg_types = xcalloc(len + 1, sizeof(ffi_type *));
|
133
|
-
|
134
|
-
for (i = 0; i < RARRAY_LEN(args); i++) {
|
135
|
-
int type = NUM2INT(RARRAY_AREF(args, i));
|
136
|
-
arg_types[i] = INT2FFI_TYPE(type);
|
137
|
-
}
|
138
|
-
arg_types[len] = NULL;
|
139
|
-
|
140
|
-
result = ffi_prep_cif(cif, nabi, len, rtype, arg_types);
|
141
|
-
|
142
|
-
if (result)
|
143
|
-
rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
|
176
|
+
cif->arg_types = NULL;
|
144
177
|
|
145
178
|
return self;
|
146
179
|
}
|
@@ -167,54 +200,160 @@ function_call(int argc, VALUE argv[], VALUE self)
|
|
167
200
|
{
|
168
201
|
struct nogvl_ffi_call_args args = { 0 };
|
169
202
|
fiddle_generic *generic_args;
|
170
|
-
VALUE cfunc
|
203
|
+
VALUE cfunc;
|
204
|
+
VALUE abi;
|
205
|
+
VALUE arg_types;
|
206
|
+
VALUE cPointer;
|
207
|
+
VALUE is_variadic;
|
208
|
+
int n_arg_types;
|
209
|
+
int n_fixed_args = 0;
|
210
|
+
int n_call_args = 0;
|
171
211
|
int i;
|
212
|
+
int i_call;
|
213
|
+
VALUE converted_args = Qnil;
|
172
214
|
VALUE alloc_buffer = 0;
|
173
215
|
|
174
216
|
cfunc = rb_iv_get(self, "@ptr");
|
175
|
-
|
217
|
+
abi = rb_iv_get(self, "@abi");
|
218
|
+
arg_types = rb_iv_get(self, "@argument_types");
|
176
219
|
cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
220
|
+
is_variadic = rb_iv_get(self, "@is_variadic");
|
221
|
+
|
222
|
+
n_arg_types = RARRAY_LENINT(arg_types);
|
223
|
+
n_fixed_args = n_arg_types;
|
224
|
+
if (RTEST(is_variadic)) {
|
225
|
+
if (argc < n_arg_types) {
|
226
|
+
rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS);
|
227
|
+
}
|
228
|
+
if (((argc - n_arg_types) % 2) != 0) {
|
229
|
+
rb_raise(rb_eArgError,
|
230
|
+
"variadic arguments must be type and value pairs: "
|
231
|
+
"%"PRIsVALUE,
|
232
|
+
rb_ary_new_from_values(argc, argv));
|
233
|
+
}
|
234
|
+
n_call_args = n_arg_types + ((argc - n_arg_types) / 2);
|
181
235
|
}
|
236
|
+
else {
|
237
|
+
if (argc != n_arg_types) {
|
238
|
+
rb_error_arity(argc, n_arg_types, n_arg_types);
|
239
|
+
}
|
240
|
+
n_call_args = n_arg_types;
|
241
|
+
}
|
242
|
+
Check_Max_Args("the number of arguments", n_call_args);
|
182
243
|
|
183
244
|
TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);
|
184
245
|
|
185
|
-
if (
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
246
|
+
if (is_variadic && args.cif->arg_types) {
|
247
|
+
xfree(args.cif->arg_types);
|
248
|
+
args.cif->arg_types = NULL;
|
249
|
+
}
|
250
|
+
|
251
|
+
if (!args.cif->arg_types) {
|
252
|
+
VALUE fixed_arg_types = arg_types;
|
253
|
+
VALUE return_type;
|
254
|
+
int c_return_type;
|
255
|
+
ffi_type *ffi_return_type;
|
256
|
+
ffi_type **ffi_arg_types;
|
257
|
+
ffi_status result;
|
258
|
+
|
259
|
+
arg_types = rb_ary_dup(fixed_arg_types);
|
260
|
+
for (i = n_fixed_args; i < argc; i += 2) {
|
261
|
+
VALUE arg_type = argv[i];
|
262
|
+
int c_arg_type;
|
263
|
+
arg_type = rb_fiddle_type_ensure(arg_type);
|
264
|
+
c_arg_type = NUM2INT(arg_type);
|
265
|
+
(void)INT2FFI_TYPE(c_arg_type); /* raise */
|
266
|
+
rb_ary_push(arg_types, INT2FIX(c_arg_type));
|
267
|
+
}
|
268
|
+
|
269
|
+
return_type = rb_iv_get(self, "@return_type");
|
270
|
+
c_return_type = FIX2INT(return_type);
|
271
|
+
ffi_return_type = INT2FFI_TYPE(c_return_type);
|
272
|
+
|
273
|
+
ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *));
|
274
|
+
for (i_call = 0; i_call < n_call_args; i_call++) {
|
275
|
+
VALUE arg_type;
|
276
|
+
int c_arg_type;
|
277
|
+
arg_type = RARRAY_AREF(arg_types, i_call);
|
278
|
+
c_arg_type = FIX2INT(arg_type);
|
279
|
+
ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type);
|
280
|
+
}
|
281
|
+
ffi_arg_types[i_call] = NULL;
|
282
|
+
|
283
|
+
if (is_variadic) {
|
284
|
+
#ifdef HAVE_FFI_PREP_CIF_VAR
|
285
|
+
result = ffi_prep_cif_var(args.cif,
|
286
|
+
FIX2INT(abi),
|
287
|
+
n_fixed_args,
|
288
|
+
n_call_args,
|
289
|
+
ffi_return_type,
|
290
|
+
ffi_arg_types);
|
291
|
+
#else
|
292
|
+
/* This code is never used because ffi_prep_cif_var()
|
293
|
+
* availability check is done in #initialize. */
|
294
|
+
result = FFI_BAD_TYPEDEF;
|
295
|
+
#endif
|
296
|
+
}
|
297
|
+
else {
|
298
|
+
result = ffi_prep_cif(args.cif,
|
299
|
+
FIX2INT(abi),
|
300
|
+
n_call_args,
|
301
|
+
ffi_return_type,
|
302
|
+
ffi_arg_types);
|
303
|
+
}
|
304
|
+
if (result != FFI_OK) {
|
305
|
+
xfree(ffi_arg_types);
|
306
|
+
args.cif->arg_types = NULL;
|
307
|
+
rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
|
308
|
+
}
|
192
309
|
}
|
193
310
|
|
194
311
|
generic_args = ALLOCV(alloc_buffer,
|
195
|
-
|
312
|
+
sizeof(fiddle_generic) * n_call_args +
|
313
|
+
sizeof(void *) * (n_call_args + 1));
|
196
314
|
args.values = (void **)((char *)generic_args +
|
197
|
-
|
198
|
-
|
199
|
-
for (i = 0
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
315
|
+
sizeof(fiddle_generic) * n_call_args);
|
316
|
+
|
317
|
+
for (i = 0, i_call = 0;
|
318
|
+
i < argc && i_call < n_call_args;
|
319
|
+
i++, i_call++) {
|
320
|
+
VALUE arg_type;
|
321
|
+
int c_arg_type;
|
322
|
+
VALUE original_src;
|
323
|
+
VALUE src;
|
324
|
+
arg_type = RARRAY_AREF(arg_types, i_call);
|
325
|
+
c_arg_type = FIX2INT(arg_type);
|
326
|
+
if (i >= n_fixed_args) {
|
327
|
+
i++;
|
328
|
+
}
|
329
|
+
src = argv[i];
|
330
|
+
|
331
|
+
if (c_arg_type == TYPE_VOIDP) {
|
332
|
+
if (NIL_P(src)) {
|
333
|
+
src = INT2FIX(0);
|
334
|
+
}
|
335
|
+
else if (cPointer != CLASS_OF(src)) {
|
336
|
+
src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
|
337
|
+
if (NIL_P(converted_args)) {
|
338
|
+
converted_args = rb_ary_new();
|
339
|
+
}
|
340
|
+
rb_ary_push(converted_args, src);
|
341
|
+
}
|
342
|
+
src = rb_Integer(src);
|
343
|
+
}
|
344
|
+
|
345
|
+
original_src = src;
|
346
|
+
VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]);
|
347
|
+
if (src != original_src) {
|
348
|
+
if (NIL_P(converted_args)) {
|
349
|
+
converted_args = rb_ary_new();
|
350
|
+
}
|
351
|
+
rb_ary_push(converted_args, src);
|
352
|
+
}
|
353
|
+
args.values[i_call] = (void *)&generic_args[i_call];
|
215
354
|
}
|
216
|
-
args.values[
|
217
|
-
args.fn = NUM2PTR(cfunc);
|
355
|
+
args.values[i_call] = NULL;
|
356
|
+
args.fn = (void(*)(void))NUM2PTR(cfunc);
|
218
357
|
|
219
358
|
(void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
|
220
359
|
|