@param [Type, Symbol] return_type return type for the function @param [Array<Type, Symbol>] param_types array of parameters types @param [Hash] options see {FFI::FunctionType} for available options @return [self] A new Function instance.
Define a function from a Proc or a block.
@overload initialize(return_type, param_types, options = {}) { |i| ... }
@yieldparam i parameters for the function
@overload initialize(return_type, param_types, proc, options = {})
@param [Proc] proc
static VALUE
function_initialize(int argc, VALUE* argv, VALUE self)
{
VALUE rbReturnType = Qnil, rbParamTypes = Qnil, rbProc = Qnil, rbOptions = Qnil;
VALUE rbFunctionInfo = Qnil;
VALUE infoArgv[3];
int nargs;
nargs = rb_scan_args(argc, argv, "22", &rbReturnType, &rbParamTypes, &rbProc, &rbOptions);
/*
* Callback with block,
* e.g. Function.new(:int, [ :int ]) { |i| blah }
* or Function.new(:int, [ :int ], { :convention => :stdcall }) { |i| blah }
*/
if (rb_block_given_p()) {
if (nargs > 3) {
rb_raise(rb_eArgError, "cannot create function with both proc/address and block");
}
rbOptions = rbProc;
rbProc = rb_block_proc();
} else {
/* Callback with proc, or Function with address
* e.g. Function.new(:int, [ :int ], Proc.new { |i| })
* Function.new(:int, [ :int ], Proc.new { |i| }, { :convention => :stdcall })
* Function.new(:int, [ :int ], addr)
* Function.new(:int, [ :int ], addr, { :convention => :stdcall })
*/
}
infoArgv[0] = rbReturnType;
infoArgv[1] = rbParamTypes;
infoArgv[2] = rbOptions;
rbFunctionInfo = rb_class_new_instance(rbOptions != Qnil ? 3 : 2, infoArgv, rbffi_FunctionTypeClass);
function_init(self, rbFunctionInfo, rbProc);
return self;
}
static VALUE
function_attach(VALUE self, VALUE module, VALUE name)
{
Function* fn;
char var[1024];
Data_Get_Struct(self, Function, fn);
if (fn->info->parameterCount == -1) {
rb_raise(rb_eRuntimeError, "cannot attach variadic functions");
return Qnil;
}
if (!rb_obj_is_kind_of(module, rb_cModule)) {
rb_raise(rb_eRuntimeError, "trying to attach function to non-module");
return Qnil;
}
if (fn->methodHandle == NULL) {
fn->methodHandle = rbffi_MethodHandle_Alloc(fn->info, fn->base.memory.address);
}
/*
* Stash the Function in a module variable so it does not get garbage collected
*/
snprintf(var, sizeof(var), "@@%s", StringValueCStr(name));
rb_cv_set(module, var, self);
rb_define_singleton_method(module, StringValueCStr(name),
rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
rb_define_method(module, StringValueCStr(name),
rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
return self;
}
static VALUE
function_autorelease_p(VALUE self)
{
Function* fn;
Data_Get_Struct(self, Function, fn);
return fn->autorelease ? Qtrue : Qfalse;
}
static VALUE
function_set_autorelease(VALUE self, VALUE autorelease)
{
Function* fn;
Data_Get_Struct(self, Function, fn);
fn->autorelease = RTEST(autorelease);
return self;
}
static VALUE
function_autorelease_p(VALUE self)
{
Function* fn;
Data_Get_Struct(self, Function, fn);
return fn->autorelease ? Qtrue : Qfalse;
}
static VALUE
function_call(int argc, VALUE* argv, VALUE self)
{
Function* fn;
Data_Get_Struct(self, Function, fn);
return (*fn->info->invoke)(argc, argv, fn->base.memory.address, fn->info);
}
static VALUE
function_release(VALUE self)
{
Function* fn;
Data_Get_Struct(self, Function, fn);
if (fn->closure == NULL) {
rb_raise(rb_eRuntimeError, "cannot free function which was not allocated");
}
rbffi_Closure_Free(fn->closure);
fn->closure = NULL;
return self;
}
Generated with the Darkfish Rdoc Generator 2.