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.
@@ -1,5 +1,13 @@
1
- http://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz \
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/libffi-3.2.1-mswin.patch -p0
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
@@ -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
- rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
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: */
@@ -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 rb_eFiddleError;
167
+ extern VALUE rb_eFiddleDLError;
134
168
 
135
169
  VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
136
170
 
@@ -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
- if ((size_t)(len) < MAX_ARGS) { \
23
- /* OK */ \
24
- } \
25
- else { \
26
- rb_raise(rb_eTypeError, \
27
- name" is so large that it can cause integer overflow (%"fmt"d)", \
28
- (len)); \
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 *ptr = p;
35
- if (ptr->arg_types) xfree(ptr->arg_types);
36
- xfree(ptr);
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
- ffi_type **arg_types, *rtype;
95
- ffi_status result;
96
- VALUE ptr, args, ret_type, abi, kwds, ary;
97
- int i, len;
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, &args, &ret_type, &abi, &kwds);
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
- nabi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
106
- abi = INT2FIX(nabi);
107
- i = NUM2INT(ret_type);
108
- rtype = INT2FFI_TYPE(i);
109
- ret_type = INT2FIX(i);
110
-
111
- Check_Type(args, T_ARRAY);
112
- len = RARRAY_LENINT(args);
113
- Check_Max_Args("args", len);
114
- ary = rb_ary_subseq(args, 0, len);
115
- for (i = 0; i < RARRAY_LEN(args); i++) {
116
- VALUE a = RARRAY_PTR(args)[i];
117
- int type = NUM2INT(a);
118
- (void)INT2FFI_TYPE(type); /* raise */
119
- if (INT2FIX(type) != a) rb_ary_store(ary, i, INT2FIX(type));
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
- OBJ_FREEZE(ary);
165
+ #endif
122
166
 
123
167
  rb_iv_set(self, "@ptr", ptr);
124
- rb_iv_set(self, "@args", args);
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, types, cPointer;
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
- types = rb_iv_get(self, "@args");
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
- Check_Max_Args("number of arguments", argc);
179
- if (argc != (i = RARRAY_LENINT(types))) {
180
- rb_error_arity(argc, i, i);
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 (rb_safe_level() >= 1) {
186
- for (i = 0; i < argc; i++) {
187
- VALUE src = argv[i];
188
- if (OBJ_TAINTED(src)) {
189
- rb_raise(rb_eSecurityError, "tainted parameter not allowed");
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
- (size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic));
312
+ sizeof(fiddle_generic) * n_call_args +
313
+ sizeof(void *) * (n_call_args + 1));
196
314
  args.values = (void **)((char *)generic_args +
197
- (size_t)argc * sizeof(fiddle_generic));
198
-
199
- for (i = 0; i < argc; i++) {
200
- VALUE type = RARRAY_AREF(types, i);
201
- VALUE src = argv[i];
202
- int argtype = FIX2INT(type);
203
-
204
- if (argtype == TYPE_VOIDP) {
205
- if(NIL_P(src)) {
206
- src = INT2FIX(0);
207
- } else if(cPointer != CLASS_OF(src)) {
208
- src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
209
- }
210
- src = rb_Integer(src);
211
- }
212
-
213
- VALUE2GENERIC(argtype, src, &generic_args[i]);
214
- args.values[i] = (void *)&generic_args[i];
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[argc] = NULL;
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