Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid loading libpython.so if Python symbols are already loaded globally #219

Merged
merged 1 commit into from
Dec 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions src/PyCall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,55 @@ const depfile = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
isfile(depfile) || error("PyCall not properly installed. Please run Pkg.build(\"PyCall\")")
include(depfile) # generated by Pkg.build("PyCall")

hassym(lib, sym) = Libdl.dlsym_e(lib, sym) != C_NULL

function get_globaldl()
if !isdefined(:globaldl)
global const globaldl = unsafe_load(cglobal((@windows ? :jl_exe_handle : :jl_dl_handle), Ptr{Void}))
end
return globaldl
end


function get_libpythondl()
if !isdefined(:libpythondl)
global const libpythondl = Libdl.dlopen(libpython, Libdl.RTLD_GLOBAL)
end
return libpythondl
end


macro pysym(func)
:(($func, libpython))
z, zlocal = gensym(string(func)), gensym()
eval(current_module(),:(global $z = C_NULL))
z = esc(z)

quote
let $zlocal::Ptr{Void} = $z::Ptr{Void}
if $zlocal == C_NULL
if hassym(get_globaldl(), $(esc(func)))
$zlocal = Libdl.dlsym(globaldl::Ptr{Void}, $(esc(func)))
else
$zlocal = Libdl.dlsym(get_libpythondl()::Ptr{Void}, $(esc(func)))
end
global $z = $zlocal
end
$zlocal
end
end
end

macro pyglobal(name)
:(cglobal(($name, libpython)))
quote
if hassym(get_globaldl(), $(esc(name)))
Libdl.dlsym(globaldl::Ptr{Void}, $(esc(name)))
else
Libdl.dlsym(get_libpythondl()::Ptr{Void}, $(esc(name)))
end
end
end
macro pyglobalobj(name)
:(cglobal(($name, libpython), PyObject_struct))
:(convert(PyPtr, @pyglobal $(esc(name))))
end

#########################################################################
Expand Down
6 changes: 5 additions & 1 deletion src/exception.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ const pyexc = Dict{DataType, PyPtr}()
type PyIOError <: Exception end

macro pyglobalobjptr(name)
:(unsafe_load(cglobal(($name, libpython), Ptr{PyObject_struct})))
quote
sym = @pyglobal $name
ptr = convert(Ptr{PyPtr}, sym)
unsafe_load( ptr )
end
end

function pyexc_initialize()
Expand Down
9 changes: 6 additions & 3 deletions src/pyinit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ const MethodWrapperType = PyNULL()
const ufuncType = PyNULL()
const format_traceback = PyNULL()


#########################################################################

function __init__()
# issue #189
Libdl.dlopen(libpython, Libdl.RTLD_LAZY|Libdl.RTLD_DEEPBIND|Libdl.RTLD_GLOBAL)

# Check to see if the Python symbols are already defined in the global namespace of the current
# process before we try to load them from a dynamic library.
if !hassym(get_globaldl(), :Py_GetVersion)
Libdl.dlopen(libpython, Libdl.RTLD_LAZY|Libdl.RTLD_DEEPBIND|Libdl.RTLD_GLOBAL)
end
already_inited = 0 != ccall((@pysym :Py_IsInitialized), Cint, ())

if !already_inited
Expand Down