7# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
8# define RB_OBJ_STRING(obj) (obj)
11# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
12# define RB_OBJ_STRING(obj) StringValueCStr(obj)
17#define MAX_ARGS (SIZE_MAX / (sizeof(void *) + sizeof(fiddle_generic)) - 1)
19#define Check_Max_Args(name, len) \
20 Check_Max_Args_(name, len, "")
21#define Check_Max_Args_Long(name, len) \
22 Check_Max_Args_(name, len, "l")
23#define Check_Max_Args_(name, len, fmt) \
25 if ((size_t)(len) >= MAX_ARGS) { \
26 rb_raise(rb_eTypeError, \
28 "that it can cause integer overflow (%"fmt"d)", \
37 if (cif->arg_types)
xfree(cif->arg_types);
42function_memsize(
const void *p)
44 ffi_cif *
ptr = (ffi_cif *)p;
48#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
57 {0, deallocate, function_memsize,},
81normalize_argument_types(
const char *
name,
85 VALUE normalized_arg_types;
91 n_arg_types = RARRAY_LENINT(arg_types);
95 for (i = 0; i < n_arg_types; i++) {
101 if (i != n_arg_types - 1) {
103 "Fiddle::TYPE_VARIADIC must be the last argument type: "
118 return normalized_arg_types;
125 VALUE ptr, arg_types, ret_type, abi, kwargs;
129 bool is_variadic =
false;
136 if (!
NIL_P(kwargs)) {
142 static ID kw[kw_max_];
145 kw[kw_name] = rb_intern_const(
"name");
146 kw[kw_need_gvl] = rb_intern_const(
"need_gvl");
149 if (args[kw_name] !=
Qundef) {
150 name = args[kw_name];
152 if (args[kw_need_gvl] !=
Qundef) {
153 need_gvl = args[kw_need_gvl];
165 c_ret_type =
NUM2INT(ret_type);
167 ret_type =
INT2FIX(c_ret_type);
169 arg_types = normalize_argument_types(
"argument types",
172#ifndef HAVE_FFI_PREP_CIF_VAR
175 "ffi_prep_cif_var() is required in libffi "
176 "for variadic arguments");
181 rb_iv_set(self,
"@argument_types", arg_types);
182 rb_iv_set(self,
"@return_type", ret_type);
187 cif->arg_types =
NULL;
200nogvl_ffi_call(
void *
ptr)
221 int n_fixed_args = 0;
226 VALUE alloc_buffer = 0;
230 arg_types =
rb_iv_get(self,
"@argument_types");
232 is_variadic =
rb_iv_get(self,
"@is_variadic");
235 n_arg_types = RARRAY_LENINT(arg_types);
236 n_fixed_args = n_arg_types;
237 if (
RTEST(is_variadic)) {
238 if (
argc < n_arg_types) {
241 if (((
argc - n_arg_types) % 2) != 0) {
243 "variadic arguments must be type and value pairs: "
247 n_call_args = n_arg_types + ((
argc - n_arg_types) / 2);
250 if (
argc != n_arg_types) {
253 n_call_args = n_arg_types;
259 if (is_variadic && args.
cif->arg_types) {
264 if (!args.
cif->arg_types) {
265 VALUE fixed_arg_types = arg_types;
268 ffi_type *ffi_return_type;
269 ffi_type **ffi_arg_types;
273 for (i = n_fixed_args; i <
argc; i += 2) {
277 c_arg_type =
NUM2INT(arg_type);
282 return_type =
rb_iv_get(self,
"@return_type");
283 c_return_type =
FIX2INT(return_type);
286 ffi_arg_types =
xcalloc(n_call_args + 1,
sizeof(ffi_type *));
287 for (i_call = 0; i_call < n_call_args; i_call++) {
291 c_arg_type =
FIX2INT(arg_type);
294 ffi_arg_types[i_call] =
NULL;
297#ifdef HAVE_FFI_PREP_CIF_VAR
307 result = FFI_BAD_TYPEDEF;
317 if (result != FFI_OK) {
318 xfree(ffi_arg_types);
324 generic_args =
ALLOCV(alloc_buffer,
326 sizeof(
void *) * (n_call_args + 1));
327 args.
values = (
void **)((
char *)generic_args +
330 for (i = 0, i_call = 0;
331 i <
argc && i_call < n_call_args;
338 c_arg_type =
FIX2INT(arg_type);
339 if (i >= n_fixed_args) {
348 else if (cPointer !=
CLASS_OF(src)) {
350 if (
NIL_P(converted_args)) {
360 if (src != original_src) {
361 if (
NIL_P(converted_args)) {
366 args.
values[i_call] = (
void *)&generic_args[i_call];
371 if (
RTEST(need_gvl)) {
379 int errno_keep = errno;
381 int socket_error = WSAGetLastError();
442#ifdef HAVE_CONST_FFI_STDCALL
void ffi_call(ffi_cif *cif, void(*fn)(void), void *rvalue, void **avalue)
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
VALUE rb_ary_dup(VALUE ary)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_new_capa(long capa)
VALUE rb_fiddle_type_ensure(VALUE type)
#define INT2FFI_TYPE(_type)
#define VALUE2GENERIC(_type, _src, _dst)
#define GENERIC2VALUE(_type, _retval)
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
const rb_data_type_t function_data_type
VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
#define Check_Max_Args(name, len)
void Init_fiddle_function(void)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_cObject
Object class.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
#define UNLIMITED_ARGUMENTS
void rb_error_arity(int, int, int)
VALUE rb_const_get(VALUE, ID)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ID rb_intern(const char *)
VALUE rb_iv_set(VALUE, const char *, VALUE)
void rb_define_const(VALUE, const char *, VALUE)
VALUE rb_iv_get(VALUE, const char *)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_abi abi, unsigned int nfixedargs, unsigned int ntotalargs, ffi_type *rtype, ffi_type **atypes)
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type *rtype, ffi_type **atypes)
#define RARRAY_AREF(a, i)
size_t ffi_raw_size(ffi_cif *cif)
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define TypedData_Make_Struct(klass, type, data_type, sval)