summaryrefslogtreecommitdiff
path: root/lib/ffi/library.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ffi/library.rb')
-rw-r--r--lib/ffi/library.rb55
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/ffi/library.rb b/lib/ffi/library.rb
index 92d2143..c23112b 100644
--- a/lib/ffi/library.rb
+++ b/lib/ffi/library.rb
@@ -31,7 +31,7 @@
require 'ffi/dynamic_library'
module FFI
- CURRENT_PROCESS = USE_THIS_PROCESS_AS_LIBRARY = Object.new
+ CURRENT_PROCESS = USE_THIS_PROCESS_AS_LIBRARY = FFI.make_shareable(Object.new)
# @param [#to_s] lib library name
# @return [String] library name formatted for current platform
@@ -209,7 +209,7 @@ module FFI
end
raise LoadError unless function
- invokers << if arg_types.length > 0 && arg_types[arg_types.length - 1] == FFI::NativeType::VARARGS
+ invokers << if arg_types[-1] == FFI::NativeType::VARARGS
VariadicInvoker.new(function, arg_types, find_type(ret_type), options)
else
@@ -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
@@ -295,9 +296,10 @@ module FFI
# If it is a global struct, just attach directly to the pointer
s = s = type.new(address) # Assigning twice to suppress unused variable warning
self.module_eval <<-code, __FILE__, __LINE__
- @@ffi_gvar_#{mname} = s
+ @ffi_gsvars = {} unless defined?(@ffi_gsvars)
+ @ffi_gsvars[#{mname.inspect}] = s
def self.#{mname}
- @@ffi_gvar_#{mname}
+ @ffi_gsvars[#{mname.inspect}]
end
code
@@ -309,12 +311,13 @@ module FFI
# Attach to this module as mname/mname=
#
self.module_eval <<-code, __FILE__, __LINE__
- @@ffi_gvar_#{mname} = s
+ @ffi_gvars = {} unless defined?(@ffi_gvars)
+ @ffi_gvars[#{mname.inspect}] = s
def self.#{mname}
- @@ffi_gvar_#{mname}[:gvar]
+ @ffi_gvars[#{mname.inspect}][:gvar]
end
def self.#{mname}=(value)
- @@ffi_gvar_#{mname}[:gvar] = value
+ @ffi_gvars[#{mname.inspect}][:gvar] = value
end
code
@@ -539,5 +542,43 @@ module FFI
end || FFI.find_type(t)
end
+
+ # Retrieve all attached functions and their function signature
+ #
+ # This method returns a Hash of method names of attached functions connected by #attach_function and the corresponding function type.
+ # The function type responds to #return_type and #param_types which return the FFI types of the function signature.
+ #
+ # @return [Hash< Symbol => [FFI::Function, FFI::VariadicInvoker] >]
+ def attached_functions
+ @ffi_functions || {}
+ end
+
+ # Retrieve all attached variables and their type
+ #
+ # This method returns a Hash of variable names and the corresponding type or variables connected by #attach_variable .
+ #
+ # @return [Hash< Symbol => ffi_type >]
+ def attached_variables
+ (
+ (@ffi_gsvars || {}).map do |name, gvar|
+ [name, gvar.class]
+ end +
+ (@ffi_gvars || {}).map do |name, gvar|
+ [name, gvar.layout[:gvar].type]
+ end
+ ).to_h
+ end
+
+ # Freeze all definitions of the module
+ #
+ # This freezes the module's definitions, so that it can be used in a Ractor.
+ # No further methods or variables can be attached and no further enums or typedefs can be created in this module afterwards.
+ def freeze
+ instance_variables.each do |name|
+ var = instance_variable_get(name)
+ FFI.make_shareable(var)
+ end
+ nil
+ end
end
end