Esempio n. 1
0
static VALUE
dlhandle_sym(void *handle, const char *name)
{
#if defined(HAVE_DLERROR)
    const char *err;
# define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
#else
# define CHECK_DLERROR
#endif
    void (*func)() = dlsym(handle, name);

    CHECK_DLERROR;
#if defined(FUNC_STDCALL)
    if( !func ){
	int  i;
	int  len = strlen(name);
	char *name_n;
#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
	{
	    char *name_a = (char*)xmalloc(len+2);
	    strcpy(name_a, name);
	    name_n = name_a;
	    name_a[len]   = 'A';
	    name_a[len+1] = '\0';
	    func = dlsym(handle, name_a);
	    CHECK_DLERROR;
	    if( func ) goto found;
	    name_n = xrealloc(name_a, len+6);
	}
#else
	name_n = (char*)xmalloc(len+6);
#endif
	memcpy(name_n, name, len);
	name_n[len++] = '@';
	for( i = 0; i < 256; i += 4 ){
	    sprintf(name_n + len, "%d", i);
	    func = dlsym(handle, name_n);
	    CHECK_DLERROR;
	    if( func ) break;
	}
	if( func ) goto found;
	name_n[len-1] = 'A';
	name_n[len++] = '@';
	for( i = 0; i < 256; i += 4 ){
	    sprintf(name_n + len, "%d", i);
	    func = dlsym(handle, name_n);
	    CHECK_DLERROR;
	    if( func ) break;
	}
      found:
	xfree(name_n);
    }
#endif
    if( !func ){
	rb_raise(rb_eDLError, "unknown symbol \"%s\"", name);
    }

    return PTR2NUM(func);
}
Esempio n. 2
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);
}
Esempio n. 3
0
/*
 * call-seq: Fiddle.malloc(size)
 *
 * Allocate +size+ bytes of memory and return the integer memory address
 * for the allocated memory.
 */
static VALUE
rb_fiddle_malloc(VALUE self, VALUE size)
{
    void *ptr;

    ptr = (void*)ruby_xmalloc(NUM2INT(size));
    return PTR2NUM(ptr);
}
Esempio n. 4
0
/*
 * call-seq: to_i
 *
 * Returns the memory address for this handle.
 */
static VALUE
rb_fiddle_handle_to_i(VALUE self)
{
    struct dl_handle *fiddle_handle;

    TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
    return PTR2NUM(fiddle_handle);
}
Esempio n. 5
0
/*
 * call-seq: to_i
 *
 * Returns the memory address for this handle.
 */
VALUE
rb_dlhandle_to_i(VALUE self)
{
    struct dl_handle *dlhandle;

    TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
    return PTR2NUM(dlhandle);
}
Esempio n. 6
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;
}
Esempio n. 7
0
static VALUE
cr_to_ptr (VALUE self)
{
  if (NIL_P (rb_cairo__cFFIPointer))
    return Qnil;

  return rb_funcall (rb_cairo__cFFIPointer, rb_intern ("new"),
                     1, PTR2NUM (_SELF));
}
Esempio n. 8
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);
}
Esempio n. 9
0
/*
 * call-seq: DL.malloc
 *
 * Allocate +size+ bytes of memory and return the integer memory address
 * for the allocated memory.
 */
VALUE
rb_dl_malloc(VALUE self, VALUE size)
{
    void *ptr;

    rb_secure(4);
    ptr = (void*)ruby_xmalloc(NUM2INT(size));
    return PTR2NUM(ptr);
}
Esempio n. 10
0
static VALUE
cr_win32_surface_get_hdc (VALUE self)
{
  HDC hdc;

  hdc = cairo_win32_surface_get_dc (_SELF);
  if (!hdc)
    return Qnil;
  else
    return PTR2NUM (hdc);
}
Esempio n. 11
0
static VALUE
to_i(VALUE self)
{
    fiddle_closure * cl;
    void *code;

    TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);

    code = cl->code;

    return PTR2NUM(code);
}
Esempio n. 12
0
VALUE
generic_to_value(VALUE rettype, fiddle_generic retval)
{
    int type = NUM2INT(rettype);
    VALUE cPointer;

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

    switch (type) {
      case TYPE_VOID:
	return Qnil;
      case TYPE_VOIDP:
        return rb_funcall(cPointer, rb_intern("[]"), 1,
          PTR2NUM((void *)retval.pointer));
      case TYPE_CHAR:
	return INT2NUM((signed char)retval.fffi_sarg);
      case -TYPE_CHAR:
	return INT2NUM((unsigned char)retval.fffi_arg);
      case TYPE_SHORT:
	return INT2NUM((signed short)retval.fffi_sarg);
      case -TYPE_SHORT:
	return INT2NUM((unsigned short)retval.fffi_arg);
      case TYPE_INT:
	return INT2NUM((signed int)retval.fffi_sarg);
      case -TYPE_INT:
	return UINT2NUM((unsigned int)retval.fffi_arg);
      case TYPE_LONG:
	return LONG2NUM(retval.slong);
      case -TYPE_LONG:
	return ULONG2NUM(retval.ulong);
#if HAVE_LONG_LONG
      case TYPE_LONG_LONG:
	return LL2NUM(retval.slong_long);
      case -TYPE_LONG_LONG:
	return ULL2NUM(retval.ulong_long);
#endif
      case TYPE_FLOAT:
	return rb_float_new(retval.ffloat);
      case TYPE_DOUBLE:
	return rb_float_new(retval.ddouble);
      default:
	rb_raise(rb_eRuntimeError, "unknown type %d", type);
    }

    UNREACHABLE;
}
Esempio n. 13
0
VALUE
generic_to_value(VALUE rettype, fiddle_generic retval)
{
    int signed_p = 1;
    int type = NUM2INT(rettype);
    VALUE cPointer;

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

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

    switch (type) {
      case TYPE_VOID:
	return Qnil;
      case TYPE_VOIDP:
        return rb_funcall(cPointer, rb_intern("[]"), 1,
          PTR2NUM((void *)retval.pointer));
      case TYPE_CHAR:
      case TYPE_SHORT:
      case TYPE_INT:
	return INT2NUM(retval.sint);
      case TYPE_LONG:
	if (signed_p) return LONG2NUM(retval.slong);
	return ULONG2NUM(retval.ulong);
#if HAVE_LONG_LONG
      case TYPE_LONG_LONG:
	return rb_ll2inum(retval.long_long);
	break;
#endif
      case TYPE_FLOAT:
	return rb_float_new(retval.ffloat);
      case TYPE_DOUBLE:
	return rb_float_new(retval.ddouble);
      default:
	rb_raise(rb_eRuntimeError, "unknown type %d", type);
    }
}
Esempio n. 14
0
VALUE
rb_dl_value2ptr(VALUE self, VALUE val)
{
    return PTR2NUM((void*)val);
}
Esempio n. 15
0
static VALUE
fiddle_handle_sym(void *handle, VALUE symbol)
{
#if defined(HAVE_DLERROR)
    const char *err;
# define CHECK_DLERROR if ((err = dlerror()) != 0) { func = 0; }
#else
# define CHECK_DLERROR
#endif
    void (*func)();
    const char *name = SafeStringValueCStr(symbol);

    rb_secure(2);
#ifdef HAVE_DLERROR
    dlerror();
#endif
    func = (void (*)())(VALUE)dlsym(handle, name);
    CHECK_DLERROR;
#if defined(FUNC_STDCALL)
    if( !func ){
	int  i;
	int  len = (int)strlen(name);
	char *name_n;
#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
	{
	    char *name_a = (char*)xmalloc(len+2);
	    strcpy(name_a, name);
	    name_n = name_a;
	    name_a[len]   = 'A';
	    name_a[len+1] = '\0';
	    func = dlsym(handle, name_a);
	    CHECK_DLERROR;
	    if( func ) goto found;
	    name_n = xrealloc(name_a, len+6);
	}
#else
	name_n = (char*)xmalloc(len+6);
#endif
	memcpy(name_n, name, len);
	name_n[len++] = '@';
	for( i = 0; i < 256; i += 4 ){
	    sprintf(name_n + len, "%d", i);
	    func = dlsym(handle, name_n);
	    CHECK_DLERROR;
	    if( func ) break;
	}
	if( func ) goto found;
	name_n[len-1] = 'A';
	name_n[len++] = '@';
	for( i = 0; i < 256; i += 4 ){
	    sprintf(name_n + len, "%d", i);
	    func = dlsym(handle, name_n);
	    CHECK_DLERROR;
	    if( func ) break;
	}
      found:
	xfree(name_n);
    }
#endif
    if( !func ){
	rb_raise(rb_eFiddleError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
    }

    return PTR2NUM(func);
}
Esempio n. 16
0
void
Init_fiddle(void)
{
    /*
     * Document-module: Fiddle
     *
     * A libffi wrapper for Ruby.
     *
     * == Description
     *
     * Fiddle is an extension to translate a foreign function interface (FFI)
     * with ruby.
     *
     * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library
     * which provides a portable interface that allows code written in one
     * language to call code written in another language.
     *
     * == Example
     *
     * Here we will use Fiddle::Function to wrap {floor(3) from
     * libm}[http://linux.die.net/man/3/floor]
     *
     *	    require 'fiddle'
     *
     *	    libm = Fiddle.dlopen('/lib/libm.so.6')
     *
     *	    floor = Fiddle::Function.new(
     *	      libm['floor'],
     *	      [Fiddle::TYPE_DOUBLE],
     *	      Fiddle::TYPE_DOUBLE
     *	    )
     *
     *	    puts floor.call(3.14159) #=> 3.0
     *
     *
     */
    mFiddle = rb_define_module("Fiddle");

    /*
     * Document-class: Fiddle::DLError
     *
     * standard dynamic load exception
     */
    rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);

    /* Document-const: TYPE_VOID
     *
     * C type - void
     */
    rb_define_const(mFiddle, "TYPE_VOID",      INT2NUM(TYPE_VOID));

    /* Document-const: TYPE_VOIDP
     *
     * C type - void*
     */
    rb_define_const(mFiddle, "TYPE_VOIDP",     INT2NUM(TYPE_VOIDP));

    /* Document-const: TYPE_CHAR
     *
     * C type - char
     */
    rb_define_const(mFiddle, "TYPE_CHAR",      INT2NUM(TYPE_CHAR));

    /* Document-const: TYPE_SHORT
     *
     * C type - short
     */
    rb_define_const(mFiddle, "TYPE_SHORT",     INT2NUM(TYPE_SHORT));

    /* Document-const: TYPE_INT
     *
     * C type - int
     */
    rb_define_const(mFiddle, "TYPE_INT",       INT2NUM(TYPE_INT));

    /* Document-const: TYPE_LONG
     *
     * C type - long
     */
    rb_define_const(mFiddle, "TYPE_LONG",      INT2NUM(TYPE_LONG));

#if HAVE_LONG_LONG
    /* Document-const: TYPE_LONG_LONG
     *
     * C type - long long
     */
    rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
#endif

    /* Document-const: TYPE_FLOAT
     *
     * C type - float
     */
    rb_define_const(mFiddle, "TYPE_FLOAT",     INT2NUM(TYPE_FLOAT));

    /* Document-const: TYPE_DOUBLE
     *
     * C type - double
     */
    rb_define_const(mFiddle, "TYPE_DOUBLE",    INT2NUM(TYPE_DOUBLE));

    /* Document-const: TYPE_SIZE_T
     *
     * C type - size_t
     */
    rb_define_const(mFiddle, "TYPE_SIZE_T",   INT2NUM(TYPE_SIZE_T));

    /* Document-const: TYPE_SSIZE_T
     *
     * C type - ssize_t
     */
    rb_define_const(mFiddle, "TYPE_SSIZE_T",   INT2NUM(TYPE_SSIZE_T));

    /* Document-const: TYPE_PTRDIFF_T
     *
     * C type - ptrdiff_t
     */
    rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));

    /* Document-const: TYPE_INTPTR_T
     *
     * C type - intptr_t
     */
    rb_define_const(mFiddle, "TYPE_INTPTR_T",  INT2NUM(TYPE_INTPTR_T));

    /* Document-const: TYPE_UINTPTR_T
     *
     * C type - uintptr_t
     */
    rb_define_const(mFiddle, "TYPE_UINTPTR_T",  INT2NUM(TYPE_UINTPTR_T));

    /* Document-const: ALIGN_VOIDP
     *
     * The alignment size of a void*
     */
    rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));

    /* Document-const: ALIGN_CHAR
     *
     * The alignment size of a char
     */
    rb_define_const(mFiddle, "ALIGN_CHAR",  INT2NUM(ALIGN_CHAR));

    /* Document-const: ALIGN_SHORT
     *
     * The alignment size of a short
     */
    rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));

    /* Document-const: ALIGN_INT
     *
     * The alignment size of an int
     */
    rb_define_const(mFiddle, "ALIGN_INT",   INT2NUM(ALIGN_INT));

    /* Document-const: ALIGN_LONG
     *
     * The alignment size of a long
     */
    rb_define_const(mFiddle, "ALIGN_LONG",  INT2NUM(ALIGN_LONG));

#if HAVE_LONG_LONG
    /* Document-const: ALIGN_LONG_LONG
     *
     * The alignment size of a long long
     */
    rb_define_const(mFiddle, "ALIGN_LONG_LONG",  INT2NUM(ALIGN_LONG_LONG));
#endif

    /* Document-const: ALIGN_FLOAT
     *
     * The alignment size of a float
     */
    rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));

    /* Document-const: ALIGN_DOUBLE
     *
     * The alignment size of a double
     */
    rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));

    /* Document-const: ALIGN_SIZE_T
     *
     * The alignment size of a size_t
     */
    rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));

    /* Document-const: ALIGN_SSIZE_T
     *
     * The alignment size of a ssize_t
     */
    rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */

    /* Document-const: ALIGN_PTRDIFF_T
     *
     * The alignment size of a ptrdiff_t
     */
    rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));

    /* Document-const: ALIGN_INTPTR_T
     *
     * The alignment size of a intptr_t
     */
    rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));

    /* Document-const: ALIGN_UINTPTR_T
     *
     * The alignment size of a uintptr_t
     */
    rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));

    /* Document-const: WINDOWS
     *
     * Returns a boolean regarding whether the host is WIN32
     */
#if defined(_WIN32)
    rb_define_const(mFiddle, "WINDOWS", Qtrue);
#else
    rb_define_const(mFiddle, "WINDOWS", Qfalse);
#endif

    /* Document-const: SIZEOF_VOIDP
     *
     * size of a void*
     */
    rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));

    /* Document-const: SIZEOF_CHAR
     *
     * size of a char
     */
    rb_define_const(mFiddle, "SIZEOF_CHAR",  INT2NUM(sizeof(char)));

    /* Document-const: SIZEOF_SHORT
     *
     * size of a short
     */
    rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));

    /* Document-const: SIZEOF_INT
     *
     * size of an int
     */
    rb_define_const(mFiddle, "SIZEOF_INT",   INT2NUM(sizeof(int)));

    /* Document-const: SIZEOF_LONG
     *
     * size of a long
     */
    rb_define_const(mFiddle, "SIZEOF_LONG",  INT2NUM(sizeof(long)));

#if HAVE_LONG_LONG
    /* Document-const: SIZEOF_LONG_LONG
     *
     * size of a long long
     */
    rb_define_const(mFiddle, "SIZEOF_LONG_LONG",  INT2NUM(sizeof(LONG_LONG)));
#endif

    /* Document-const: SIZEOF_FLOAT
     *
     * size of a float
     */
    rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));

    /* Document-const: SIZEOF_DOUBLE
     *
     * size of a double
     */
    rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));

    /* Document-const: SIZEOF_SIZE_T
     *
     * size of a size_t
     */
    rb_define_const(mFiddle, "SIZEOF_SIZE_T",  INT2NUM(sizeof(size_t)));

    /* Document-const: SIZEOF_SSIZE_T
     *
     * size of a ssize_t
     */
    rb_define_const(mFiddle, "SIZEOF_SSIZE_T",  INT2NUM(sizeof(size_t))); /* same as size_t */

    /* Document-const: SIZEOF_PTRDIFF_T
     *
     * size of a ptrdiff_t
     */
    rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T",  INT2NUM(sizeof(ptrdiff_t)));

    /* Document-const: SIZEOF_INTPTR_T
     *
     * size of a intptr_t
     */
    rb_define_const(mFiddle, "SIZEOF_INTPTR_T",  INT2NUM(sizeof(intptr_t)));

    /* Document-const: SIZEOF_UINTPTR_T
     *
     * size of a uintptr_t
     */
    rb_define_const(mFiddle, "SIZEOF_UINTPTR_T",  INT2NUM(sizeof(uintptr_t)));

    /* Document-const: RUBY_FREE
     *
     * Address of the ruby_xfree() function
     */
    rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));

    /* Document-const: BUILD_RUBY_PLATFORM
     *
     * Platform built against (i.e. "x86_64-linux", etc.)
     *
     * See also RUBY_PLATFORM
     */
    rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));

    rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
    rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
    rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
    rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
    rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);

    Init_fiddle_function();
    Init_fiddle_closure();
    Init_fiddle_handle();
    Init_fiddle_pointer();
}
Esempio n. 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);
    }
}
Esempio n. 18
0
VALUE
rb_dlhandle_sym(VALUE self, VALUE sym)
{
    void (*func)();
    struct dl_handle *dlhandle;
    void *handle;
    const char *name;
    const char *err;
    int i;

#if defined(HAVE_DLERROR)
# define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
#else
# define CHECK_DLERROR
#endif

    rb_secure(2);

    if( sym == Qnil ){
#if defined(RTLD_NEXT)
	name = RTLD_NEXT;
#else
	name = NULL;
#endif
    }
    else{
	name = StringValuePtr(sym);
    }


    Data_Get_Struct(self, struct dl_handle, dlhandle);
    if( ! dlhandle->open ){
	rb_raise(rb_eDLError, "closed handle");
    }
    handle = dlhandle->ptr;

    func = dlsym(handle, name);
    CHECK_DLERROR;
    if( !func ){
#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
	{
	    int  len = strlen(name);
	    char *name_a = (char*)xmalloc(len+2);
	    strcpy(name_a, name);
	    name_a[len]   = 'A';
	    name_a[len+1] = '\0';
	    func = dlsym(handle, name_a);
	    xfree(name_a);
	    CHECK_DLERROR;
	    if( !func ){
		for( i = 0; i < 256; i += 4 ){
		    int  len = strlen(name);
		    char *name_n = (char*)xmalloc(len+5);
		    sprintf(name_n, "%s@%d%c", name, i, 0);
		    func = dlsym(handle, name_n);
		    xfree(name_n);
		    CHECK_DLERROR;
		    if( func )
                    {
			break;
		    }
		}
		CHECK_DLERROR;
		if( !func ){
		    rb_raise(rb_eDLError, "unknown symbol \"%s\"", name);
		}
	    }
	}
#else
	for( i = 0; i < 256; i += 4 ){
	    int  len = strlen(name);
	    char *name_n = (char*)xmalloc(len+4);
	    sprintf(name_n, "%s@%d", name, i);
	    func = dlsym(handle, name_n);
	    xfree(name_n);
	    CHECK_DLERROR;
            if( func ){
		break;
	    }
	}
	CHECK_DLERROR;
        if( !func ){
	    rb_raise(rb_eDLError, "unknown symbol \"%s\"", name);
	}
#endif
    }

    return PTR2NUM(func);
}
Esempio n. 19
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);
}
Esempio n. 20
0
void
Init_dl(void)
{
    void Init_dlhandle(void);
    void Init_dlcfunc(void);
    void Init_dlptr(void);

    rbdl_id_cdecl = rb_intern_const("cdecl");
    rbdl_id_stdcall = rb_intern_const("stdcall");

    /* Document-module: DL
     *
     * A bridge to the dlopen() or dynamic library linker function.
     *
     * == Example
     *
     *   bash $> cat > sum.c <<EOF
     *   double sum(double *arry, int len)
     *   {
     *           double ret = 0;
     *           int i;
     *           for(i = 0; i < len; i++){
     *                   ret = ret + arry[i];
     *           }
     *           return ret;
     *   }
     *
     *   double split(double num)
     *   {
     *           double ret = 0;
     *           ret = num / 2;
     *           return ret;
     *   }
     *   EOF
     *   bash $> gcc -o libsum.so -shared sum.c
     *   bash $> cat > sum.rb <<EOF
     *   require 'dl'
     *   require 'dl/import'
     *
     *   module LibSum
     *           extend DL::Importer
     *           dlload './libsum.so'
     *           extern 'double sum(double*, int)'
     *           extern 'double split(double)'
     *   end
     *
     *   a = [2.0, 3.0, 4.0]
     *
     *   sum = LibSum.sum(a.pack("d*"), a.count)
     *   p LibSum.split(sum)
     *   EOF
     *   bash $> ruby sum.rb
     *   4.5
     *
     * WIN! :-)
     */
    rb_mDL = rb_define_module("DL");

    /*
     * Document-class: DL::DLError
     *
     * standard dynamic load exception
     */
    rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError);

    /*
     * Document-class: DL::DLTypeError
     *
     * dynamic load incorrect type exception
     */
    rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError);

    /* Document-const: MAX_CALLBACK
     *
     * Maximum number of callbacks
     */
    rb_define_const(rb_mDL, "MAX_CALLBACK", INT2NUM(MAX_CALLBACK));

    /* Document-const: DLSTACK_SIZE
     *
     * Dynamic linker stack size
     */
    rb_define_const(rb_mDL, "DLSTACK_SIZE", INT2NUM(DLSTACK_SIZE));

    rb_dl_init_callbacks(rb_mDL);

    /* Document-const: RTLD_GLOBAL
     *
     * rtld DL::Handle flag.
     *
     * The symbols defined by this library will be made available for symbol
     * resolution of subsequently loaded libraries.
     */
    rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));

    /* Document-const: RTLD_LAZY
     *
     * rtld DL::Handle flag.
     *
     * Perform lazy binding.  Only resolve symbols as the code that references
     * them is executed.  If the  symbol is never referenced, then it is never
     * resolved.  (Lazy binding is only performed for function references;
     * references to variables are always immediately bound when the library
     * is loaded.)
     */
    rb_define_const(rb_mDL, "RTLD_LAZY",   INT2NUM(RTLD_LAZY));

    /* Document-const: RTLD_NOW
     *
     * rtld DL::Handle flag.
     *
     * If this value is specified or the environment variable LD_BIND_NOW is
     * set to a nonempty string, all undefined symbols in the library are
     * resolved before dlopen() returns.  If this cannot be done an error is
     * returned.
     */
    rb_define_const(rb_mDL, "RTLD_NOW",    INT2NUM(RTLD_NOW));

    /* Document-const: TYPE_VOID
     *
     * DL::CFunc type - void
     */
    rb_define_const(rb_mDL, "TYPE_VOID",  INT2NUM(DLTYPE_VOID));

    /* Document-const: TYPE_VOIDP
     *
     * DL::CFunc type - void*
     */
    rb_define_const(rb_mDL, "TYPE_VOIDP",  INT2NUM(DLTYPE_VOIDP));

    /* Document-const: TYPE_CHAR
     *
     * DL::CFunc type - char
     */
    rb_define_const(rb_mDL, "TYPE_CHAR",  INT2NUM(DLTYPE_CHAR));

    /* Document-const: TYPE_SHORT
     *
     * DL::CFunc type - short
     */
    rb_define_const(rb_mDL, "TYPE_SHORT",  INT2NUM(DLTYPE_SHORT));

    /* Document-const: TYPE_INT
     *
     * DL::CFunc type - int
     */
    rb_define_const(rb_mDL, "TYPE_INT",  INT2NUM(DLTYPE_INT));

    /* Document-const: TYPE_LONG
     *
     * DL::CFunc type - long
     */
    rb_define_const(rb_mDL, "TYPE_LONG",  INT2NUM(DLTYPE_LONG));

#if HAVE_LONG_LONG
    /* Document-const: TYPE_LONG_LONG
     *
     * DL::CFunc type - long long
     */
    rb_define_const(rb_mDL, "TYPE_LONG_LONG",  INT2NUM(DLTYPE_LONG_LONG));
#endif

    /* Document-const: TYPE_FLOAT
     *
     * DL::CFunc type - float
     */
    rb_define_const(rb_mDL, "TYPE_FLOAT",  INT2NUM(DLTYPE_FLOAT));

    /* Document-const: TYPE_DOUBLE
     *
     * DL::CFunc type - double
     */
    rb_define_const(rb_mDL, "TYPE_DOUBLE",  INT2NUM(DLTYPE_DOUBLE));

    /* Document-const: ALIGN_VOIDP
     *
     * The Offset of a struct void* and a void*
     */
    rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));

    /* Document-const: ALIGN_CHAR
     *
     * The Offset of a struct char and a char
     */
    rb_define_const(rb_mDL, "ALIGN_CHAR",  INT2NUM(ALIGN_CHAR));

    /* Document-const: ALIGN_SHORT
     *
     * The Offset of a struct short and a short
     */
    rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));

    /* Document-const: ALIGN_INT
     *
     * The Offset of a struct int and a int
     */
    rb_define_const(rb_mDL, "ALIGN_INT",   INT2NUM(ALIGN_INT));

    /* Document-const: ALIGN_LONG
     *
     * The Offset of a struct long and a long
     */
    rb_define_const(rb_mDL, "ALIGN_LONG",  INT2NUM(ALIGN_LONG));

#if HAVE_LONG_LONG
    /* Document-const: ALIGN_LONG_LONG
     *
     * The Offset of a struct long long and a long long
     */
    rb_define_const(rb_mDL, "ALIGN_LONG_LONG",  INT2NUM(ALIGN_LONG_LONG));
#endif

    /* Document-const: ALIGN_FLOAT
     *
     * The Offset of a struct float and a float
     */
    rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));

    /* Document-const: ALIGN_DOUBLE
     *
     * The Offset of a struct double and a double
     */
    rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));

    /* Document-const: SIZEOF_VOIDP
     *
     * OS Dependent - sizeof(void*)
     */
    rb_define_const(rb_mDL, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));

    /* Document-const: SIZEOF_CHAR
     *
     * OS Dependent - sizeof(char)
     */
    rb_define_const(rb_mDL, "SIZEOF_CHAR",  INT2NUM(sizeof(char)));

    /* Document-const: SIZEOF_SHORT
     *
     * OS Dependent - sizeof(short)
     */
    rb_define_const(rb_mDL, "SIZEOF_SHORT", INT2NUM(sizeof(short)));

    /* Document-const: SIZEOF_INT
     *
     * OS Dependent - sizeof(int)
     */
    rb_define_const(rb_mDL, "SIZEOF_INT",   INT2NUM(sizeof(int)));

    /* Document-const: SIZEOF_LONG
     *
     * OS Dependent - sizeof(long)
     */
    rb_define_const(rb_mDL, "SIZEOF_LONG",  INT2NUM(sizeof(long)));

#if HAVE_LONG_LONG
    /* Document-const: SIZEOF_LONG_LONG
     *
     * OS Dependent - sizeof(long long)
     */
    rb_define_const(rb_mDL, "SIZEOF_LONG_LONG",  INT2NUM(sizeof(LONG_LONG)));
#endif

    /* Document-const: SIZEOF_FLOAT
     *
     * OS Dependent - sizeof(float)
     */
    rb_define_const(rb_mDL, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));

    /* Document-const: SIZEOF_DOUBLE
     *
     * OS Dependent - sizeof(double)
     */
    rb_define_const(rb_mDL, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));

    rb_define_module_function(rb_mDL, "dlwrap", rb_dl_value2ptr, 1);
    rb_define_module_function(rb_mDL, "dlunwrap", rb_dl_ptr2value, 1);

    rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1);
    rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1);
    rb_define_module_function(rb_mDL, "realloc", rb_dl_realloc, 2);
    rb_define_module_function(rb_mDL, "free", rb_dl_free, 1);

    /* Document-const: RUBY_FREE
     *
     * Address of the ruby_xfree() function
     */
    rb_define_const(rb_mDL, "RUBY_FREE", PTR2NUM(ruby_xfree));

    /* Document-const: BUILD_RUBY_PLATFORM
     *
     * Platform built against (i.e. "x86_64-linux", etc.)
     *
     * See also RUBY_PLATFORM
     */
    rb_define_const(rb_mDL, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));

    /* Document-const: BUILD_RUBY_VERSION
     *
     * Ruby Version built. (i.e. "1.9.3")
     *
     * See also RUBY_VERSION
     */
    rb_define_const(rb_mDL, "BUILD_RUBY_VERSION",  rb_str_new2(RUBY_VERSION));

    Init_dlhandle();
    Init_dlcfunc();
    Init_dlptr();
}
Esempio n. 21
0
/*
 * call-seq: Fiddle.dlwrap(val)
 *
 * Returns a memory pointer of a function's hexadecimal address location +val+
 *
 * Example:
 *
 *   lib = Fiddle.dlopen('/lib64/libc-2.15.so')
 *   => #<Fiddle::Handle:0x00000001342460>
 *
 *   Fiddle.dlwrap(lib['strcpy'].to_s(16))
 *   => 25522520
 */
static VALUE
rb_fiddle_value2ptr(VALUE self, VALUE val)
{
    return PTR2NUM((void*)val);
}