fiddle 1.0.0 → 1.0.1
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.
- 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
|
|