Exemple #1
0
static VALUE
id2ref(VALUE obj, SEL sel, VALUE objid)
{
#if SIZEOF_LONG == SIZEOF_VOIDP
#define NUM2PTR(x) NUM2ULONG(x)
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
#define NUM2PTR(x) NUM2ULL(x)
#endif
    VALUE ptr;
    void *p0;

    rb_secure(4);
    ptr = NUM2PTR(objid);
    p0 = (void *)ptr;

    if (ptr == Qtrue) return Qtrue;
    if (ptr == Qfalse) return Qfalse;
    if (ptr == Qnil) return Qnil;
    if (FIXNUM_P(ptr) || SYMBOL_P(ptr))
	return ptr;

    if (auto_zone_is_valid_pointer(__auto_zone, p0)) {
	auto_memory_type_t type = 
	    auto_zone_get_layout_type(__auto_zone, p0);
	if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
	    && (NATIVE((VALUE)p0)
		|| (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
	    return (VALUE)p0;
    }
    rb_raise(rb_eRangeError, "%p is not id value", p0);
}
Exemple #2
0
/*
 * call-seq: Fiddle.free(addr)
 *
 * Free the memory at address +addr+
 */
VALUE
rb_fiddle_free(VALUE self, VALUE addr)
{
    void *ptr = NUM2PTR(addr);

    ruby_xfree(ptr);
    return Qnil;
}
Exemple #3
0
/*
 * call-seq: Fiddle.realloc(addr, size)
 *
 * Change the size of the memory allocated at the memory location +addr+ to
 * +size+ bytes.  Returns the memory address of the reallocated memory, which
 * may be different than the address passed in.
 */
static VALUE
rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
{
    void *ptr = NUM2PTR(addr);

    ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
    return PTR2NUM(ptr);
}
Exemple #4
0
/*
 * call-seq: DL.realloc(addr, size)
 *
 * Change the size of the memory allocated at the memory location +addr+ to
 * +size+ bytes.  Returns the memory address of the reallocated memory, which
 * may be different than the address passed in.
 */
VALUE
rb_dl_realloc(VALUE self, VALUE addr, VALUE size)
{
    void *ptr = NUM2PTR(addr);

    rb_secure(4);
    ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
    return PTR2NUM(ptr);
}
Exemple #5
0
static VALUE
initialize(int argc, VALUE argv[], VALUE self)
{
    ffi_cif * cif;
    ffi_type **arg_types, *rtype;
    ffi_status result;
    VALUE ptr, args, ret_type, abi, kwds, ary;
    int i, len;
    int nabi;
    void *cfunc;

    rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds);
    ptr = rb_Integer(ptr);
    cfunc = NUM2PTR(ptr);
    PTR2NUM(cfunc);
    nabi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
    abi = INT2FIX(nabi);
    i = NUM2INT(ret_type);
    rtype = INT2FFI_TYPE(i);
    ret_type = INT2FIX(i);

    Check_Type(args, T_ARRAY);
    len = RARRAY_LENINT(args);
    Check_Max_Args("args", len);
    ary = rb_ary_subseq(args, 0, len);
    for (i = 0; i < RARRAY_LEN(args); i++) {
	VALUE a = RARRAY_PTR(args)[i];
	int type = NUM2INT(a);
	(void)INT2FFI_TYPE(type); /* raise */
	if (INT2FIX(type) != a) rb_ary_store(ary, i, INT2FIX(type));
    }
    OBJ_FREEZE(ary);

    rb_iv_set(self, "@ptr", ptr);
    rb_iv_set(self, "@args", args);
    rb_iv_set(self, "@return_type", ret_type);
    rb_iv_set(self, "@abi", abi);

    if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);

    TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);

    arg_types = xcalloc(len + 1, sizeof(ffi_type *));

    for (i = 0; i < RARRAY_LEN(args); i++) {
	int type = NUM2INT(RARRAY_AREF(args, i));
	arg_types[i] = INT2FFI_TYPE(type);
    }
    arg_types[len] = NULL;

    result = ffi_prep_cif(cif, nabi, len, rtype, arg_types);

    if (result)
	rb_raise(rb_eRuntimeError, "error creating CIF %d", result);

    return self;
}
Exemple #6
0
/*
 * call-seq: DL.free(addr)
 *
 * Free the memory at address +addr+
 */
VALUE
rb_dl_free(VALUE self, VALUE addr)
{
    void *ptr = NUM2PTR(addr);

    rb_secure(4);
    ruby_xfree(ptr);
    return Qnil;
}
Exemple #7
0
static inline freefunc_t
get_freefunc(VALUE func)
{
    if (NIL_P(func)) {
	return NULL;
    }
    if (rb_dlcfunc_kind_p(func)) {
	return (freefunc_t)(VALUE)RCFUNC_DATA(func)->ptr;
    }
    return (freefunc_t)(VALUE)NUM2PTR(rb_Integer(func));
}
Exemple #8
0
static VALUE
function_call(int argc, VALUE argv[], VALUE self)
{
    ffi_cif * cif;
    fiddle_generic retval;
    fiddle_generic *generic_args;
    void **values;
    VALUE cfunc, types, cPointer;
    int i;

    cfunc    = rb_iv_get(self, "@ptr");
    types    = rb_iv_get(self, "@args");
    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    if(argc != RARRAY_LENINT(types)) {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
		argc, RARRAY_LENINT(types));
    }

    TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);

    values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
    generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));

    for (i = 0; i < argc; i++) {
	VALUE type = RARRAY_PTR(types)[i];
	VALUE src = argv[i];

	if(NUM2INT(type) == TYPE_VOIDP) {
	    if(NIL_P(src)) {
		src = INT2NUM(0);
	    } else if(cPointer != CLASS_OF(src)) {
	        src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
	    }
	    src = rb_Integer(src);
	}

	VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
	values[i] = (void *)&generic_args[i];
    }
    values[argc] = NULL;

    ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);

    rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
#if defined(HAVE_WINDOWS_H)
    rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
#endif

    xfree(values);
    xfree(generic_args);

    return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
}
static VALUE
cr_win32_printing_surface_initialize (VALUE self, VALUE hdc)
{
  cairo_surface_t *surface = NULL;

  surface = cairo_win32_printing_surface_create (NUM2PTR (hdc));
  cr_surface_check_status (surface);
  DATA_PTR (self) = surface;
  if (rb_block_given_p ())
    yield_and_finish (self);
  return Qnil;
}
Exemple #10
0
static inline freefunc_t
get_freefunc(VALUE func, volatile VALUE *wrap)
{
    VALUE addrnum;
    if (NIL_P(func)) {
	*wrap = 0;
	return NULL;
    }
    addrnum = rb_Integer(func);
    *wrap = (addrnum != func) ? func : 0;
    return (freefunc_t)(VALUE)NUM2PTR(addrnum);
}
Exemple #11
0
void
value_to_generic(int type, VALUE src, fiddle_generic * dst)
{
    switch (type) {
      case TYPE_VOID:
	break;
      case TYPE_VOIDP:
	dst->pointer = NUM2PTR(rb_Integer(src));
	break;
      case TYPE_CHAR:
	dst->schar = (signed char)NUM2INT(src);
	break;
      case -TYPE_CHAR:
	dst->uchar = (unsigned char)NUM2UINT(src);
	break;
      case TYPE_SHORT:
	dst->sshort = (unsigned short)NUM2INT(src);
	break;
      case -TYPE_SHORT:
	dst->sshort = (signed short)NUM2UINT(src);
	break;
      case TYPE_INT:
	dst->sint = NUM2INT(src);
	break;
      case -TYPE_INT:
	dst->uint = NUM2UINT(src);
	break;
      case TYPE_LONG:
	dst->slong = NUM2LONG(src);
	break;
      case -TYPE_LONG:
	dst->ulong = NUM2ULONG(src);
	break;
#if HAVE_LONG_LONG
      case TYPE_LONG_LONG:
	dst->slong_long = NUM2LL(src);
	break;
      case -TYPE_LONG_LONG:
	dst->ulong_long = NUM2ULL(src);
	break;
#endif
      case TYPE_FLOAT:
	dst->ffloat = (float)NUM2DBL(src);
	break;
      case TYPE_DOUBLE:
	dst->ddouble = NUM2DBL(src);
	break;
      default:
	rb_raise(rb_eRuntimeError, "unknown type %d", type);
    }
}
Exemple #12
0
static inline freefunc_t
get_freefunc(VALUE func, volatile VALUE *wrap)
{
    VALUE addrnum;
    if (NIL_P(func)) {
	*wrap = 0;
	return NULL;
    }
    if (rb_dlcfunc_kind_p(func)) {
	*wrap = func;
	return (freefunc_t)(VALUE)RCFUNC_DATA(func)->ptr;
    }
    addrnum = rb_Integer(func);
    *wrap = (addrnum != func) ? func : 0;
    return (freefunc_t)(VALUE)NUM2PTR(addrnum);
}
Exemple #13
0
static VALUE rb_struct_read(VALUE self, VALUE protocol) {
  DEBUG_FUNCTION_ENTRY();
  protocol_method_table *pmt;

  //We haven't been supplied with a method table, try retrieving it...
  int has_gmt = rb_respond_to(protocol, rb_intern("get_protocol_method_table"));

  if (has_gmt)
    pmt = NUM2PTR(rb_funcall(protocol, get_protocol_method_table_ID, 0));
  else
    pmt = &default_table;

  VALUE ret = struct_read(self, protocol, pmt);

  DEBUG_FUNCTION_EXIT();
  return ret;
}
Exemple #14
0
void
value_to_generic(int type, VALUE src, fiddle_generic * dst)
{
    int signed_p = 1;

    if (type < 0) {
	type = -1 * type;
	signed_p = 0;
    }

    switch (type) {
      case TYPE_VOID:
	break;
      case TYPE_VOIDP:
	dst->pointer = NUM2PTR(rb_Integer(src));
	break;
      case TYPE_CHAR:
	dst->schar = NUM2INT(src);
	break;
      case TYPE_SHORT:
	dst->sshort = NUM2INT(src);
	break;
      case TYPE_INT:
	dst->sint = NUM2INT(src);
	break;
      case TYPE_LONG:
	if (signed_p)
	    dst->slong = NUM2LONG(src);
	else
	    dst->ulong = NUM2LONG(src);
	break;
#if HAVE_LONG_LONG
      case TYPE_LONG_LONG:
	dst->long_long = rb_big2ull(src);
	break;
#endif
      case TYPE_FLOAT:
	dst->ffloat = (float)NUM2DBL(src);
	break;
      case TYPE_DOUBLE:
	dst->ddouble = NUM2DBL(src);
	break;
      default:
	rb_raise(rb_eRuntimeError, "unknown type %d", type);
    }
}
Exemple #15
0
static VALUE
cr_s_wrap (VALUE self, VALUE pointer)
{
  VALUE result;
  VALUE rb_cr;
  cairo_t *cr;

  if (NIL_P (rb_cairo__cFFIPointer))
    {
      rb_raise (rb_eNotImpError,
                "%s: FFI::Pointer is required",
                rb_id2name (rb_frame_this_func ()));
    }

  if (!RTEST (rb_obj_is_kind_of (pointer, rb_cairo__cFFIPointer)))
    {
      rb_raise (rb_eArgError,
                "must be FFI::Pointer: %s",
                rb_cairo__inspect (pointer));
    }

  {
    VALUE rb_cr_address;
    rb_cr_address = rb_funcall (pointer, rb_intern ("address"), 0);
    cr = NUM2PTR (rb_cr_address);
    cr_check_status (cr);
  }

  rb_cr = rb_obj_alloc (self);
  cairo_reference (cr);
  DATA_PTR (rb_cr) = cr;
  rb_ivar_set (rb_cr, cr_id_surface, Qnil);

  if (rb_block_given_p ())
    {
      result = rb_ensure (rb_yield, rb_cr, cr_destroy_with_destroy_check, rb_cr);
    }
  else
    {
      result = rb_cr;
    }

  return result;
}
void
PLCB__viewhandle_stop(SV *pp)
{
    AV *req = (AV *)SvRV(pp);
    PLCB_t *parent = parent_from_req(req);
    SV **tmp, *vhsv;

    tmp = av_fetch(req, PLCB_VHIDX_VHANDLE, 0);
    if (!tmp) {
        return;
    }

    vhsv = *tmp;
    if (SvIOK(vhsv)) {
        lcb_VIEWHANDLE vh = NUM2PTR(lcb_VIEWHANDLE, SvUV(vhsv));
        lcb_view_cancel(parent->instance, vh);
        av_store(req, PLCB_VHIDX_VHANDLE, SvREFCNT_inc(&PL_sv_undef));
        av_store(req, PLCB_VHIDX_ISDONE, SvREFCNT_inc(&PL_sv_yes));
        SvREFCNT_dec((SV *)req);
    }
}
Exemple #17
0
void
callback(ffi_cif *cif, void *resp, void **args, void *ctx)
{
    VALUE self      = (VALUE)ctx;
    VALUE rbargs    = rb_iv_get(self, "@args");
    VALUE ctype     = rb_iv_get(self, "@ctype");
    int argc        = RARRAY_LENINT(rbargs);
    VALUE params    = rb_ary_tmp_new(argc);
    VALUE ret;
    VALUE cPointer;
    int i, type;

    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    for (i = 0; i < argc; i++) {
        type = NUM2INT(RARRAY_PTR(rbargs)[i]);
        switch (type) {
        case TYPE_VOID:
            argc = 0;
            break;
        case TYPE_INT:
            rb_ary_push(params, INT2NUM(*(int *)args[i]));
            break;
        case -TYPE_INT:
            rb_ary_push(params, UINT2NUM(*(unsigned int *)args[i]));
            break;
        case TYPE_VOIDP:
            rb_ary_push(params,
                        rb_funcall(cPointer, rb_intern("[]"), 1,
                                   PTR2NUM(*(void **)args[i])));
            break;
        case TYPE_LONG:
            rb_ary_push(params, LONG2NUM(*(long *)args[i]));
            break;
        case -TYPE_LONG:
            rb_ary_push(params, ULONG2NUM(*(unsigned long *)args[i]));
            break;
        case TYPE_CHAR:
            rb_ary_push(params, INT2NUM(*(signed char *)args[i]));
            break;
        case -TYPE_CHAR:
            rb_ary_push(params, UINT2NUM(*(unsigned char *)args[i]));
            break;
        case TYPE_SHORT:
            rb_ary_push(params, INT2NUM(*(signed short *)args[i]));
            break;
        case -TYPE_SHORT:
            rb_ary_push(params, UINT2NUM(*(unsigned short *)args[i]));
            break;
        case TYPE_DOUBLE:
            rb_ary_push(params, rb_float_new(*(double *)args[i]));
            break;
        case TYPE_FLOAT:
            rb_ary_push(params, rb_float_new(*(float *)args[i]));
            break;
#if HAVE_LONG_LONG
        case TYPE_LONG_LONG:
            rb_ary_push(params, LL2NUM(*(LONG_LONG *)args[i]));
            break;
        case -TYPE_LONG_LONG:
            rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)args[i]));
            break;
#endif
        default:
            rb_raise(rb_eRuntimeError, "closure args: %d", type);
        }
    }

    ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_PTR(params));
    RB_GC_GUARD(params);

    type = NUM2INT(ctype);
    switch (type) {
    case TYPE_VOID:
        break;
    case TYPE_LONG:
        *(long *)resp = NUM2LONG(ret);
        break;
    case -TYPE_LONG:
        *(unsigned long *)resp = NUM2ULONG(ret);
        break;
    case TYPE_CHAR:
    case TYPE_SHORT:
    case TYPE_INT:
        *(ffi_sarg *)resp = NUM2INT(ret);
        break;
    case -TYPE_CHAR:
    case -TYPE_SHORT:
    case -TYPE_INT:
        *(ffi_arg *)resp = NUM2UINT(ret);
        break;
    case TYPE_VOIDP:
        *(void **)resp = NUM2PTR(ret);
        break;
    case TYPE_DOUBLE:
        *(double *)resp = NUM2DBL(ret);
        break;
    case TYPE_FLOAT:
        *(float *)resp = (float)NUM2DBL(ret);
        break;
#if HAVE_LONG_LONG
    case TYPE_LONG_LONG:
        *(LONG_LONG *)resp = NUM2LL(ret);
        break;
    case -TYPE_LONG_LONG:
        *(unsigned LONG_LONG *)resp = NUM2ULL(ret);
        break;
#endif
    default:
        rb_raise(rb_eRuntimeError, "closure retval: %d", type);
    }
}
Exemple #18
0
void
callback(ffi_cif *cif, void *resp, void **args, void *ctx)
{
    VALUE self      = (VALUE)ctx;
    VALUE rbargs    = rb_iv_get(self, "@args");
    VALUE ctype     = rb_iv_get(self, "@ctype");
    int argc        = RARRAY_LENINT(rbargs);
    VALUE *params   = xcalloc(argc, sizeof(VALUE *));
    VALUE ret;
    VALUE cPointer;
    int i, type;

    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    for (i = 0; i < argc; i++) {
        type = NUM2INT(RARRAY_PTR(rbargs)[i]);
        switch (type) {
	  case TYPE_VOID:
	    argc = 0;
	    break;
	  case TYPE_INT:
	    params[i] = INT2NUM(*(int *)args[i]);
	    break;
	  case TYPE_VOIDP:
            params[i] = rb_funcall(cPointer, rb_intern("[]"), 1,
              PTR2NUM(*(void **)args[i]));
	    break;
	  case TYPE_LONG:
	    params[i] = LONG2NUM(*(long *)args[i]);
	    break;
	  case TYPE_CHAR:
	    params[i] = INT2NUM(*(char *)args[i]);
	    break;
	  case TYPE_DOUBLE:
	    params[i] = rb_float_new(*(double *)args[i]);
	    break;
	  case TYPE_FLOAT:
	    params[i] = rb_float_new(*(float *)args[i]);
	    break;
#if HAVE_LONG_LONG
	  case TYPE_LONG_LONG:
	    params[i] = rb_ull2inum(*(unsigned LONG_LONG *)args[i]);
	    break;
#endif
	  default:
	    rb_raise(rb_eRuntimeError, "closure args: %d", type);
        }
    }

    ret = rb_funcall2(self, rb_intern("call"), argc, params);

    type = NUM2INT(ctype);
    switch (type) {
      case TYPE_VOID:
	break;
      case TYPE_LONG:
	*(long *)resp = NUM2LONG(ret);
	break;
      case TYPE_CHAR:
	*(char *)resp = NUM2INT(ret);
	break;
      case TYPE_VOIDP:
	*(void **)resp = NUM2PTR(ret);
	break;
      case TYPE_INT:
	*(int *)resp = NUM2INT(ret);
	break;
      case TYPE_DOUBLE:
	*(double *)resp = NUM2DBL(ret);
	break;
      case TYPE_FLOAT:
	*(float *)resp = (float)NUM2DBL(ret);
	break;
#if HAVE_LONG_LONG
      case TYPE_LONG_LONG:
	*(unsigned LONG_LONG *)resp = rb_big2ull(ret);
	break;
#endif
      default:
	rb_raise(rb_eRuntimeError, "closure retval: %d", type);
    }
    xfree(params);
}
Exemple #19
0
VALUE
rb_dl_ptr2value(VALUE self, VALUE addr)
{
    rb_secure(4);
    return (VALUE)NUM2PTR(addr);
}
Exemple #20
0
/*
 * call-seq: Fiddle.dlunwrap(addr)
 *
 * Returns the hexadecimal representation of a memory pointer address +addr+
 *
 * Example:
 *
 *   lib = Fiddle.dlopen('/lib64/libc-2.15.so')
 *   => #<Fiddle::Handle:0x00000001342460>
 *
 *   lib['strcpy'].to_s(16)
 *   => "7f59de6dd240"
 *
 *   Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16)))
 *   => "7f59de6dd240"
 */
VALUE
rb_fiddle_ptr2value(VALUE self, VALUE addr)
{
    return (VALUE)NUM2PTR(addr);
}
static VALUE
cr_win32_surface_initialize (int argc, VALUE *argv, VALUE self)
{
  cairo_surface_t *surface = NULL;
  VALUE arg1, arg2, arg3, arg4;
  VALUE hdc, format, width, height;

  rb_scan_args (argc, argv, "13", &arg1, &arg2, &arg3, &arg4);

  switch (argc)
    {
    case 1:
      hdc = arg1;
      surface = cairo_win32_surface_create (NUM2PTR (hdc));
      break;
    case 2:
      width = arg1;
      height = arg2;
      surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
                                                     NUM2INT (width),
                                                     NUM2INT (height));
      break;
    case 3:
      if (NIL_P (arg1) ||
          (rb_cairo__is_kind_of (arg1, rb_cNumeric) &&
           NUM2INT (arg1) != CAIRO_FORMAT_RGB24))
        {
#  if CAIRO_CHECK_VERSION(1, 4, 0)
          HDC win32_hdc;
          hdc = arg1;
          width = arg2;
          height = arg3;
          win32_hdc = NIL_P (hdc) ? NULL : NUM2PTR (hdc);
          surface = cairo_win32_surface_create_with_ddb (win32_hdc,
                                                         CAIRO_FORMAT_RGB24,
                                                         NUM2INT (width),
                                                         NUM2INT (height));
#  else
          rb_raise (rb_eArgError,
                    "Cairo::Win32Surface.new(hdc, width, height) "
                    "is available since cairo >= 1.4.0");
#  endif
        }
      else
        {
          format = arg1;
          width = arg2;
          height = arg3;
          surface = cairo_win32_surface_create_with_dib (RVAL2CRFORMAT (format),
                                                         NUM2INT (width),
                                                         NUM2INT (height));
        }
      break;
    case 4:
      {
#  if CAIRO_CHECK_VERSION(1, 4, 0)
        HDC win32_hdc;
        hdc = arg1;
        format = arg2;
        width = arg3;
        height = arg4;
        win32_hdc = NIL_P (hdc) ? NULL : (HDC) NUM2UINT (hdc);
        surface = cairo_win32_surface_create_with_ddb (win32_hdc,
                                                       RVAL2CRFORMAT (format),
                                                       NUM2INT (width),
                                                       NUM2INT (height));
#  else
        rb_raise (rb_eArgError,
                  "Cairo::Win32Surface.new(hdc, format, width, height) "
                  "is available since cairo >= 1.4.0");
#  endif
      }
      break;
    }

  if (!surface)
    rb_cairo_check_status (CAIRO_STATUS_INVALID_FORMAT);
  cr_surface_check_status (surface);
  DATA_PTR (self) = surface;
  if (rb_block_given_p ())
    yield_and_finish (self);
  return Qnil;
}
Exemple #22
0
static VALUE
function_call(int argc, VALUE argv[], VALUE self)
{
    struct nogvl_ffi_call_args args = { 0 };
    fiddle_generic *generic_args;
    VALUE cfunc, types, cPointer;
    int i;
    VALUE alloc_buffer = 0;

    cfunc    = rb_iv_get(self, "@ptr");
    types    = rb_iv_get(self, "@args");
    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    Check_Max_Args("number of arguments", argc);
    if (argc != (i = RARRAY_LENINT(types))) {
	rb_error_arity(argc, i, i);
    }

    TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);

    if (rb_safe_level() >= 1) {
	for (i = 0; i < argc; i++) {
	    VALUE src = argv[i];
	    if (OBJ_TAINTED(src)) {
		rb_raise(rb_eSecurityError, "tainted parameter not allowed");
	    }
	}
    }

    generic_args = ALLOCV(alloc_buffer,
	(size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic));
    args.values = (void **)((char *)generic_args +
			    (size_t)argc * sizeof(fiddle_generic));

    for (i = 0; i < argc; i++) {
	VALUE type = RARRAY_AREF(types, i);
	VALUE src = argv[i];
	int argtype = FIX2INT(type);

	if (argtype == TYPE_VOIDP) {
	    if(NIL_P(src)) {
		src = INT2FIX(0);
	    } else if(cPointer != CLASS_OF(src)) {
		src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
	    }
	    src = rb_Integer(src);
	}

	VALUE2GENERIC(argtype, src, &generic_args[i]);
	args.values[i] = (void *)&generic_args[i];
    }
    args.values[argc] = NULL;
    args.fn = NUM2PTR(cfunc);

    (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);

    rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
#if defined(_WIN32)
    rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
#endif

    ALLOCV_END(alloc_buffer);

    return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval);
}