In Files

Parent

FFI::Function

Public Class Methods

new(p1, p2, p3 = v3, p4 = v4) click to toggle source

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

Public Instance Methods

attach(m, name) click to toggle source
@param [Module] m
@param [String] name
@return [self]
Attach a Function to the Module +m+ as +name+.
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;
}
autorelease() click to toggle source
static VALUE
function_autorelease_p(VALUE self)
{
    Function* fn;

    Data_Get_Struct(self, Function, fn);

    return fn->autorelease ? Qtrue : Qfalse;
}
autorelease = autorelease click to toggle source
@param [Boolean] autorelease
@return [self]
Set +autorelease+ attribute (See {Pointer}).
static VALUE
function_set_autorelease(VALUE self, VALUE autorelease)
{
    Function* fn;

    Data_Get_Struct(self, Function, fn);

    fn->autorelease = RTEST(autorelease);

    return self;
}
autorelease?() click to toggle source
static VALUE
function_autorelease_p(VALUE self)
{
    Function* fn;

    Data_Get_Struct(self, Function, fn);

    return fn->autorelease ? Qtrue : Qfalse;
}
call(*args) click to toggle source
@param [Array] args function arguments
@return [FFI::Type]
Call the function
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);
}
free click to toggle source
@return [self]
Free memory allocated by Function.
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;
}
initialize_copy(other) click to toggle source
@return [nil]
DO NOT CALL THIS METHOD
static VALUE
function_initialize_copy(VALUE self, VALUE other)
{
    rb_raise(rb_eRuntimeError, "cannot duplicate function instances");
    return Qnil;
}

[Validate]

Generated with the Darkfish Rdoc Generator 2.