Ruby 2.4

Fiddle::Function

class Fiddle::Function

Parent:Object

描述

C函数的表示

例子

'strcpy'

@libc = Fiddle.dlopen "/lib/libc.so.6" #=> #<Fiddle::Handle:0x00000001d7a8d8> f = Fiddle::Function.new( @libc['strcpy'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP) #=> #<Fiddle::Function:0x00000001d8ee00> buff = "000" #=> "000" str = f.call(buff, "123") #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000> str.to_s => "123"

ABI检查

@libc = Fiddle.dlopen "/lib/libc.so.6" #=> #<Fiddle::Handle:0x00000001d7a8d8> f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) #=> #<Fiddle::Function:0x00000001d8ee00> f.abi == Fiddle::Function::DEFAULT #=> true

常量

DEFAULT

DEFAULT

Default ABI

STDCALL

STDCALL

FFI执行WIN32 stdcall约定

属性

abiR

函数的ABI。

nameR

这个函数的名字

ptrR

这个函数的地址

公共类方法

new(ptr, args, ret_type, abi = DEFAULT) Show source

构造一个Function对象。

  • ptr 是一个Fiddle :: Handle的引用函数

  • args是传递给ptr函数的一个参数数组

  • ret_type 是函数的返回类型

  • abi 是函数的ABI

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; }

公共实例方法

call(*args) Show source

调用构造函数args。如果在多线程进程中运行,调用者必须确保底层函数以线程安全方式调用。

有关示例,请参阅Fiddle :: Function

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 }

to_i() Show source

该函数的整数存储位置

# File ext/fiddle/lib/fiddle/function.rb, line 13 def to_i ptr.to_i end