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