A direct accessor to a function in a C library
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'>
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); }
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; }
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; \ }
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; \ }
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); }
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; }
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); }
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; }
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; }
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; }
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); }
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; }
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); }
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.