core/native_method.rb
##
# A wrapper for a calling a function in a shared library that has been
# attached via rb_define_method().
#
# The primitive slot for a NativeMethod points to the nmethod_call primitive
# which dispatches to the underlying C function.
module Rubinius
class NativeMethod < Executable
attr_reader :file
attr_reader :name
attr_reader :arity
#
# Load a dynamic library at path +library+, having name +extension_name+.
#
# +extension_name+ is used to calculate what Init_ function to call.
#
def self.load_extension(library, extension_name)
name = "Init_#{extension_name.sub(/\..*$/, '')}"
begin
lib = FFI::DynamicLibrary.new(library, FFI::DynamicLibrary::RTLD_NOW | FFI::DynamicLibrary::RTLD_GLOBAL)
rescue LoadError => e
raise LoadError::InvalidExtensionError, e.message, e
end
ver = lib.find_symbol("__X_rubinius_version")
unless ver
raise LoadError::InvalidExtensionError, "Out-of-date or not compatible. Recompile or reinstall gem (#{library})"
end
sym = lib.find_symbol(name)
unless sym
raise LoadError::InvalidExtensionError, "Missing Init_ function (#{name})"
end
entry_point = load_entry_point(library, name.to_sym, sym)
entry_point.invoke(:init, Rubinius, self, [], nil)
true
end
#
# Load extension and generate a NativeMethod for its entry point.
#
# +ptr+ is an FFI::Pointer to a C function.
#
def self.load_entry_point(library, name, ptr)
Rubinius.primitive :nativemethod_load_extension_entry_point
raise PrimitiveFailure, "Rubinius::NativeMethod3load_entry_point primitive failed: #{library}"
end
def lines
nil
end
def literals
nil
end
def line_from_ip(i)
0
end
def first_line
0
end
def defined_line
0
end
def active_path
@file
end
def scope
nil
end
end
end