Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions ext/ffi_c/Function.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef struct Function_ {

static void function_mark(void *data);
static void function_free(void *data);
static size_t function_memsize(const void *data);
static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
Expand All @@ -100,10 +101,12 @@ static const rb_data_type_t function_data_type = {
.function = {
.dmark = function_mark,
.dfree = function_free,
.dsize = NULL,
.dsize = function_memsize,
},
.parent = &rbffi_pointer_data_type,
.flags = RUBY_TYPED_FREE_IMMEDIATELY
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
// macro to update VALUE references, as to trigger write barriers.
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};

VALUE rbffi_FunctionClass = Qnil;
Expand Down Expand Up @@ -153,9 +156,9 @@ function_allocate(VALUE klass)
obj = TypedData_Make_Struct(klass, Function, &function_data_type, fn);

fn->base.memory.flags = MEM_RD;
fn->base.rbParent = Qnil;
fn->rbProc = Qnil;
fn->rbFunctionInfo = Qnil;
RB_OBJ_WRITE(obj, &fn->base.rbParent, Qnil);
RB_OBJ_WRITE(obj, &fn->rbProc, Qnil);
RB_OBJ_WRITE(obj, &fn->rbFunctionInfo, Qnil);
fn->autorelease = true;

return obj;
Expand Down Expand Up @@ -185,6 +188,20 @@ function_free(void *data)
xfree(fn);
}

static size_t
function_memsize(const void *data)
{
const Function *fn = (const Function *)data;
size_t memsize = sizeof(Function);

// Would be nice to better account for MethodHandle and Closure too.
if (fn->closure) {
memsize += sizeof(Closure);
}

return memsize;
}

/*
* @param [Type, Symbol] return_type return type for the function
* @param [Array<Type, Symbol>] param_types array of parameters types
Expand Down Expand Up @@ -313,15 +330,15 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)

TypedData_Get_Struct(self, Function, &function_data_type, fn);

fn->rbFunctionInfo = rbFunctionInfo;
RB_OBJ_WRITE(self, &fn->rbFunctionInfo, rbFunctionInfo);

TypedData_Get_Struct(fn->rbFunctionInfo, FunctionType, &rbffi_fntype_data_type, fn->info);

if (rb_obj_is_kind_of(rbProc, rbffi_PointerClass)) {
Pointer* orig;
TypedData_Get_Struct(rbProc, Pointer, &rbffi_pointer_data_type, orig);
fn->base.memory = orig->memory;
fn->base.rbParent = rbProc;
RB_OBJ_WRITE(self, &fn->base.rbParent, rbProc);

} else if (rb_obj_is_kind_of(rbProc, rb_cProc) || rb_respond_to(rbProc, id_call)) {
if (fn->info->closurePool == NULL) {
Expand Down Expand Up @@ -357,7 +374,7 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
rb_obj_classname(rbProc));
}

fn->rbProc = rbProc;
RB_OBJ_WRITE(self, &fn->rbProc, rbProc);

return self;
}
Expand Down
8 changes: 8 additions & 0 deletions spec/ffi/function_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,12 @@ class << self; self; end
fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
expect { fp.free }.to raise_error RuntimeError
end

it 'has a memsize function', skip: RUBY_ENGINE != "ruby" do
base_size = ObjectSpace.memsize_of(Object.new)

function = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd'))
size = ObjectSpace.memsize_of(function)
expect(size).to be > base_size
end
end