In Files

  • dl/cfunc.c

DL::CFunc

A direct accessor to a function in a C library

Example

libc_so = "/lib64/libc.so.6"
=> "/lib64/libc.so.6"
libc = DL::dlopen(libc_so)
=> #<DL::Handle:0x00000000e05b00>
@cfunc = DL::CFunc.new(libc['strcpy'], DL::TYPE_VOIDP, 'strcpy')
=> #<DL::CFunc:0x000000012daec0 ptr=0x007f62ca5a8300 type=1 name='strcpy'>

Public Class Methods

last_error() click to toggle source

Returns the last error for the current executing thread

 
               static VALUE
rb_dl_get_last_error(VALUE self)
{
    return rb_thread_local_aref(rb_thread_current(), id_last_error);
}
            
DL::CFunc.new(address, type=DL::TYPE_VOID, name=nil, calltype=:cdecl) click to toggle source

Create a new function that points to address with an optional return type of type, a name of name and a calltype of calltype.

 
               static VALUE
rb_dlcfunc_initialize(int argc, VALUE argv[], VALUE self)
{
    VALUE addr, name, type, calltype, addrnum;
    struct cfunc_data *data;
    void *saddr;
    const char *sname;

    rb_scan_args(argc, argv, "13", &addr, &type, &name, &calltype);

    addrnum = rb_Integer(addr);
    saddr = (void*)(NUM2PTR(addrnum));
    sname = NIL_P(name) ? NULL : StringValuePtr(name);

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, data);
    if( data->name ) xfree(data->name);
    data->ptr  = saddr;
    data->name = sname ? strdup(sname) : 0;
    data->type = NIL_P(type) ? DLTYPE_VOID : NUM2INT(type);
    data->calltype = NIL_P(calltype) ? CFUNC_CDECL : SYM2ID(calltype);
    data->wrap = (addrnum == addr) ? 0 : addr;

    return Qnil;
}
            
win32_last_error() click to toggle source

Returns the last win32 error for the current executing thread

 
               static VALUE
rb_dl_get_win32_last_error(VALUE self)
{
    return rb_thread_local_aref(rb_thread_current(), id_win32_last_error);
}
            

Public Instance Methods

dlcfunc[ary] => some_value click to toggle source

Calls the function pointer passing in ary as values to the underlying C function. The return value depends on the ctype.

 
               static VALUE
rb_dlcfunc_call(VALUE self, VALUE ary)
{
    struct cfunc_data *cfunc;
    int i;
    DLSTACK_TYPE stack[DLSTACK_SIZE];
    VALUE result = Qnil;

    memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);
    Check_Type(ary, T_ARRAY);

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

    if( cfunc->ptr == 0 ){
        rb_raise(rb_eDLError, "can't call null-function");
        return Qnil;
    }

    for( i = 0; i < RARRAY_LEN(ary); i++ ){
        VALUE arg;
        if( i >= DLSTACK_SIZE ){
            rb_raise(rb_eDLError, "too many arguments (stack overflow)");
        }
        arg = rb_to_int(RARRAY_PTR(ary)[i]);
        rb_check_safe_obj(arg);
        if (FIXNUM_P(arg)) {
            stack[i] = (DLSTACK_TYPE)FIX2LONG(arg);
        }
        else if (RB_TYPE_P(arg, T_BIGNUM)) {
            unsigned long ls[(sizeof(DLSTACK_TYPE) + sizeof(long) - 1)/sizeof(long)];
            DLSTACK_TYPE d;
            int j;
            rb_big_pack(arg, ls, sizeof(ls)/sizeof(*ls));
            d = 0;
            for (j = 0; j < (int)(sizeof(ls)/sizeof(*ls)); j++)
                d |= (DLSTACK_TYPE)ls[j] << (j * sizeof(long) * CHAR_BIT);
            stack[i] = d;
        }
        else {
            Check_Type(arg, T_FIXNUM);
        }
    }

    /* calltype == CFUNC_CDECL */
    if( cfunc->calltype == CFUNC_CDECL
#ifndef FUNC_STDCALL
        || cfunc->calltype == CFUNC_STDCALL
#endif
        ){
        switch( cfunc->type ){
        case DLTYPE_VOID:
#define CASE(n) case n: { \
            DECL_FUNC_CDECL(f,void,DLSTACK_PROTO##n,cfunc->ptr); \
            f(DLSTACK_ARGS##n(stack)); \
            result = Qnil; \
}
            
call(ary) => some_value click to toggle source

Calls the function pointer passing in ary as values to the underlying C function. The return value depends on the ctype.

 
               static VALUE
rb_dlcfunc_call(VALUE self, VALUE ary)
{
    struct cfunc_data *cfunc;
    int i;
    DLSTACK_TYPE stack[DLSTACK_SIZE];
    VALUE result = Qnil;

    memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);
    Check_Type(ary, T_ARRAY);

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

    if( cfunc->ptr == 0 ){
        rb_raise(rb_eDLError, "can't call null-function");
        return Qnil;
    }

    for( i = 0; i < RARRAY_LEN(ary); i++ ){
        VALUE arg;
        if( i >= DLSTACK_SIZE ){
            rb_raise(rb_eDLError, "too many arguments (stack overflow)");
        }
        arg = rb_to_int(RARRAY_PTR(ary)[i]);
        rb_check_safe_obj(arg);
        if (FIXNUM_P(arg)) {
            stack[i] = (DLSTACK_TYPE)FIX2LONG(arg);
        }
        else if (RB_TYPE_P(arg, T_BIGNUM)) {
            unsigned long ls[(sizeof(DLSTACK_TYPE) + sizeof(long) - 1)/sizeof(long)];
            DLSTACK_TYPE d;
            int j;
            rb_big_pack(arg, ls, sizeof(ls)/sizeof(*ls));
            d = 0;
            for (j = 0; j < (int)(sizeof(ls)/sizeof(*ls)); j++)
                d |= (DLSTACK_TYPE)ls[j] << (j * sizeof(long) * CHAR_BIT);
            stack[i] = d;
        }
        else {
            Check_Type(arg, T_FIXNUM);
        }
    }

    /* calltype == CFUNC_CDECL */
    if( cfunc->calltype == CFUNC_CDECL
#ifndef FUNC_STDCALL
        || cfunc->calltype == CFUNC_STDCALL
#endif
        ){
        switch( cfunc->type ){
        case DLTYPE_VOID:
#define CASE(n) case n: { \
            DECL_FUNC_CDECL(f,void,DLSTACK_PROTO##n,cfunc->ptr); \
            f(DLSTACK_ARGS##n(stack)); \
            result = Qnil; \
}
            
calltype => symbol click to toggle source

Get the call type of this function.

 
               static VALUE
rb_dlcfunc_calltype(VALUE self)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    return ID2SYM(cfunc->calltype);
}
            
calltype = symbol click to toggle source

Set the call type for this function.

 
               static VALUE
rb_dlcfunc_set_calltype(VALUE self, VALUE sym)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    cfunc->calltype = SYM2ID(sym);
    return sym;
}
            
ctype => num click to toggle source

Get the C function return value type. See DL for a list of constants corresponding to this method’s return value.

 
               static VALUE
rb_dlcfunc_ctype(VALUE self)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    return INT2NUM(cfunc->type);
}
            
ctype = type click to toggle source

Set the C function return value type to type.

 
               static VALUE
rb_dlcfunc_set_ctype(VALUE self, VALUE ctype)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    cfunc->type = NUM2INT(ctype);
    return ctype;
}
            
inspect click to toggle source

Returns a string formatted with an easily readable representation of the internal state of the DL::CFunc

 
               static VALUE
rb_dlcfunc_inspect(VALUE self)
{
    VALUE val;
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

    val = rb_sprintf("#<DL::CFunc:%p ptr=%p type=%d name='%s'>",
             cfunc,
             cfunc->ptr,
             cfunc->type,
             cfunc->name ? cfunc->name : "");
    OBJ_TAINT(val);
    return val;
}
            
name => str click to toggle source

Get the name of this function

 
               static VALUE
rb_dlcfunc_name(VALUE self)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    return cfunc->name ? rb_tainted_str_new2(cfunc->name) : Qnil;
}
            
ptr click to toggle source

Get the underlying function pointer as a DL::CPtr object.

 
               static VALUE
rb_dlcfunc_ptr(VALUE self)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    return PTR2NUM(cfunc->ptr);
}
            
ptr = pointer click to toggle source

Set the underlying function pointer to a DL::CPtr named pointer.

 
               static VALUE
rb_dlcfunc_set_ptr(VALUE self, VALUE addr)
{
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
    cfunc->ptr = NUM2PTR(addr);

    return Qnil;
}
            
to_i => integer click to toggle source

Returns the memory location of this function pointer as an integer.

 
               static VALUE
rb_dlcfunc_to_i(VALUE self)
{
  struct cfunc_data *cfunc;

  TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);
  return PTR2NUM(cfunc->ptr);
}
            
to_s click to toggle source

Returns a string formatted with an easily readable representation of the internal state of the DL::CFunc

 
               static VALUE
rb_dlcfunc_inspect(VALUE self)
{
    VALUE val;
    struct cfunc_data *cfunc;

    TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

    val = rb_sprintf("#<DL::CFunc:%p ptr=%p type=%d name='%s'>",
             cfunc,
             cfunc->ptr,
             cfunc->type,
             cfunc->name ? cfunc->name : "");
    OBJ_TAINT(val);
    return val;
}
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus