lib/pycall/libpython.rb in pycall-0.1.0.alpha.20170419 vs lib/pycall/libpython.rb in pycall-0.1.0.alpha.20170426
- old
+ new
@@ -24,10 +24,12 @@
end
private_class_method
def self.find_libpython(python = nil)
+ debug = (ENV['DEBUG_FIND_LIBPYTHON'] == '1')
+ dir_sep = File::ALT_SEPARATOR || File::SEPARATOR
python ||= 'python'
python_config = investigate_python_config(python)
v = python_config[:VERSION]
libprefix = FFI::Platform::LIBPREFIX
@@ -40,22 +42,26 @@
libs << File.basename(lib, File.extname(lib))
end
libs << "#{libprefix}python#{v}" << "#{libprefix}python"
libs.uniq!
+ $stderr.puts "DEBUG(find_libpython) libs: #{libs.inspect}" if debug
+
executable = python_config[:executable]
libpaths = [ python_config[:LIBDIR] ]
if FFI::Platform.windows?
libpaths << File.dirname(executable)
else
libpaths << File.expand_path('../../lib', executable)
end
libpaths << python_config[:PYTHONFRAMEWORKPREFIX] if FFI::Platform.mac?
exec_prefix = python_config[:exec_prefix]
- libpaths << exec_prefix << File.join(exec_prefix, 'lib')
+ libpaths << exec_prefix << [exec_prefix, 'lib'].join(dir_sep)
libpaths.compact!
+ $stderr.puts "DEBUG(find_libpython) libpaths: #{libpaths.inspect}" if debug
+
unless ENV['PYTHONHOME']
# PYTHONHOME tells python where to look for both pure python and binary modules.
# When it is set, it replaces both `prefix` and `exec_prefix`
# and we thus need to set it to both in case they differ.
# This is also what the documentation recommends.
@@ -86,32 +92,46 @@
end
# Find libpython (we hope):
libsuffix = FFI::Platform::LIBSUFFIX
multiarch = python_config[:MULTIARCH] || python_config[:multiarch]
- dir_sep = File::ALT_SEPARATOR || File::SEPARATOR
libs.each do |lib|
libpaths.each do |libpath|
# NOTE: File.join doesn't use File::ALT_SEPARATOR
libpath_libs = [ [libpath, lib].join(dir_sep) ]
libpath_libs << [libpath, multiarch, lib].join(dir_sep) if multiarch
libpath_libs.each do |libpath_lib|
[
libpath_lib,
"#{libpath_lib}.#{libsuffix}"
].each do |fullname|
- next unless File.file?(fullname)
+ unless File.file?(fullname)
+ $stderr.puts "DEBUG(find_libpython) Unable to find #{fullname}" if debug
+ next
+ end
begin
- libs = ffi_lib(fullname)
- return libs.first
+ dynlibs = ffi_lib(fullname)
+ $stderr.puts "DEBUG(find_libpython) ffi_lib(#{fullname.inspect}) = #{dynlibs.inspect}" if debug
+ return dynlibs.first
rescue LoadError
# skip load error
end
end
end
end
end
+
+ # Find libpython in the system path
+ libs.each do |lib|
+ begin
+ dynlibs = ffi_lib(lib)
+ $stderr.puts "DEBUG(find_libpython) ffi_lib(#{lib.inspect}) = #{dynlibs.inspect}" if debug
+ return dynlibs.first
+ rescue LoadError
+ # skip load error
+ end
+ end
end
def self.investigate_python_config(python)
python_env = { 'PYTHONIOENCODING' => 'UTF-8' }
IO.popen(python_env, [python, python_investigator_py], 'r') do |io|
@@ -129,10 +149,22 @@
end
ffi_lib_flags :lazy, :global
libpython = find_libpython ENV['PYTHON']
+ attach_function :Py_GetVersion, [], :string
+ PYTHON_DESCRIPTION = LibPython.Py_GetVersion().freeze
+ PYTHON_VERSION = PYTHON_DESCRIPTION.split(' ', 2)[0].freeze
+
+ # --- types ---
+
+ if PYTHON_VERSION < '3.2'
+ typedef :long, :Py_hash_t
+ else
+ typedef :ssize_t, :Py_hash_t
+ end
+
# --- global variables ---
attach_variable :_Py_NoneStruct, PyObjectStruct
def self.Py_None
@@ -171,11 +203,10 @@
attach_variable :PyFunction_Type, PyObjectStruct
attach_variable :PyMethod_Type, PyObjectStruct
# --- functions ---
- attach_function :Py_GetVersion, [], :string
attach_function :Py_InitializeEx, [:int], :void
attach_function :Py_IsInitialized, [], :int
attach_function :PySys_SetArgvEx, [:int, :pointer, :int], :void
# Reference count
@@ -192,10 +223,11 @@
attach_function :PyObject_GetItem, [PyObjectStruct.by_ref, PyObjectStruct.by_ref], PyObjectStruct.by_ref
attach_function :PyObject_SetItem, [PyObjectStruct.by_ref, PyObjectStruct.by_ref, PyObjectStruct.by_ref], :int
attach_function :PyObject_Call, [PyObjectStruct.by_ref, PyObjectStruct.by_ref, PyObjectStruct.by_ref], PyObjectStruct.by_ref
attach_function :PyObject_IsInstance, [PyObjectStruct.by_ref, PyObjectStruct.by_ref], :int
attach_function :PyObject_Dir, [PyObjectStruct.by_ref], PyObjectStruct.by_ref
+ attach_function :PyObject_Hash, [PyObjectStruct.by_ref], :Py_hash_t
attach_function :PyObject_Repr, [PyObjectStruct.by_ref], PyObjectStruct.by_ref
attach_function :PyObject_Str, [PyObjectStruct.by_ref], PyObjectStruct.by_ref
attach_function :PyObject_Type, [PyObjectStruct.by_ref], PyObjectStruct.by_ref
attach_function :PyCallable_Check, [PyObjectStruct.by_ref], :int
@@ -337,8 +369,12 @@
attach_function :PyErr_NormalizeException, [:pointer, :pointer, :pointer], :void
public_class_method
end
- PYTHON_DESCRIPTION = LibPython.Py_GetVersion().freeze
- PYTHON_VERSION = PYTHON_DESCRIPTION.split(' ', 2)[0].freeze
+ PYTHON_DESCRIPTION = LibPython::PYTHON_DESCRIPTION
+ PYTHON_VERSION = LibPython::PYTHON_VERSION
+
+ def self.unicode_literals?
+ @unicode_literals ||= (PYTHON_VERSION >= '3.0')
+ end
end