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