summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Kanis <lars@greiz-reinsdorf.de>2023-05-08 08:57:10 +0200
committerLars Kanis <lars@greiz-reinsdorf.de>2023-05-08 08:57:10 +0200
commitb448759f390bb50eceb9b48a307efeba68c3581c (patch)
tree1e8b91533f99a3934a8eb83567d3a545df6a39ec
parentb0ed4717ea08c61d8a1d0c9205cedff3e33805e3 (diff)
downloadffi-b448759f390bb50eceb9b48a307efeba68c3581c.tar.gz
Register functions in Ruby code
For consistency and to ease proting to JRuby and Truffleruby.
-rw-r--r--ext/ffi_c/Function.c12
-rw-r--r--lib/ffi/function.rb17
-rw-r--r--lib/ffi/library.rb1
-rw-r--r--lib/ffi/variadic.rb3
-rw-r--r--spec/ffi/library_spec.rb2
-rw-r--r--spec/ffi/variadic_spec.rb2
6 files changed, 22 insertions, 15 deletions
diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c
index d0b65fb..7810056 100644
--- a/ext/ffi_c/Function.c
+++ b/ext/ffi_c/Function.c
@@ -492,7 +492,6 @@ static VALUE
function_attach(VALUE self, VALUE module, VALUE name)
{
Function* fn;
- VALUE funcs;
StringValue(name);
TypedData_Get_Struct(self, Function, &function_data_type, fn);
@@ -511,17 +510,6 @@ function_attach(VALUE self, VALUE module, VALUE name)
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 and can be inspected by attached_functions
- */
-
- funcs = rb_iv_get(module, "@ffi_functions");
- if (RB_NIL_P(funcs)) {
- funcs = rb_hash_new();
- rb_iv_set(module, "@ffi_functions", funcs);
- }
- rb_hash_aset(funcs, rb_str_intern(name), self);
-
rb_define_singleton_method(module, StringValueCStr(name),
rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
diff --git a/lib/ffi/function.rb b/lib/ffi/function.rb
index b4469be..ac4daf0 100644
--- a/lib/ffi/function.rb
+++ b/lib/ffi/function.rb
@@ -50,5 +50,22 @@ module FFI
type.param_types
end
end
+
+ # Stash the Function in a module variable so it can be inspected by attached_functions.
+ # On CRuby it also ensures that it does not get garbage collected.
+ module RegisterAttach
+ def attach(mod, name)
+ funcs = mod.instance_variable_get("@ffi_functions")
+ unless funcs
+ funcs = {}
+ mod.instance_variable_set("@ffi_functions", funcs)
+ end
+ funcs[name.to_sym] = self
+ # Jump to the native attach method of CRuby, JRuby or Tuffleruby
+ super
+ end
+ end
+ private_constant :RegisterAttach
+ prepend RegisterAttach
end
end
diff --git a/lib/ffi/library.rb b/lib/ffi/library.rb
index 9394902..c23112b 100644
--- a/lib/ffi/library.rb
+++ b/lib/ffi/library.rb
@@ -281,6 +281,7 @@ module FFI
# Attach C variable +cname+ to this module.
def attach_variable(mname, a1, a2 = nil)
cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ]
+ mname = mname.to_sym
address = nil
ffi_libraries.each do |lib|
begin
diff --git a/lib/ffi/variadic.rb b/lib/ffi/variadic.rb
index 389c53c..ee33409 100644
--- a/lib/ffi/variadic.rb
+++ b/lib/ffi/variadic.rb
@@ -54,6 +54,7 @@ module FFI
invoker = self
params = "*args"
call = "call"
+ mname = mname.to_sym
mod.module_eval <<-code, __FILE__, __LINE__
@ffi_functions = {} unless defined?(@ffi_functions)
@ffi_functions[#{mname.inspect}] = invoker
@@ -62,7 +63,7 @@ module FFI
@ffi_functions[#{mname.inspect}].#{call}(#{params})
end
- define_method(#{mname.inspect}, &method(:#{mname}))
+ define_method(#{mname.inspect}, &method(#{mname.inspect}))
code
invoker
end
diff --git a/spec/ffi/library_spec.rb b/spec/ffi/library_spec.rb
index 1b8e8c1..9bbbd6c 100644
--- a/spec/ffi/library_spec.rb
+++ b/spec/ffi/library_spec.rb
@@ -381,7 +381,7 @@ describe "Library" do
lib = Module.new do |m|
m.extend FFI::Library
ffi_lib TestLibrary::PATH
- attach_variable :gvaro, "gvar_u32", :uint32
+ attach_variable "gvaro", "gvar_u32", :uint32
end
expect(lib.attached_variables).to eq({ gvaro: FFI::Type::UINT32 })
end
diff --git a/spec/ffi/variadic_spec.rb b/spec/ffi/variadic_spec.rb
index 21a803f..4d3f1c2 100644
--- a/spec/ffi/variadic_spec.rb
+++ b/spec/ffi/variadic_spec.rb
@@ -40,7 +40,7 @@ describe "Function with variadic arguments" do
end
it "can reveal its return and parameters" do
- fun = LibTest.attached_functions["testBlockingWRva"]
+ fun = LibTest.attached_functions[:testBlockingWRva]
expect(fun.param_types).to eq([FFI::Type::POINTER, FFI::Type::CHAR, FFI::Type::VARARGS])
expect(fun.return_type).to eq(FFI::Type::INT8)
end